{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Hyperparameters and lags search: backtesting vs one-step-ahead"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Hyperparameter and lag tuning involves systematically testing different values or combinations of hyperparameters (and/or lags) to find the optimal configuration that gives the best performance. The **skforecast** library provides two different methods to evaluate each candidate configuration:\n",
    "\n",
    "+ **Backtesting**: In this method, the model predicts several steps ahead in each iteration, using the same forecast horizon and retraining frequency strategy that would be used if the model were deployed. This simulates a real forecasting scenario where the model is retrained and updated over time. More information [here](../user_guides/backtesting.html).\n",
    "\n",
    "+ **One-Step Ahead**: Evaluates the model using only one-step-ahead predictions. This method is faster because it requires fewer iterations, but it only tests the model's performance in the immediate next time step ($t+1$).\n",
    "\n",
    "Each method uses a different evaluation strategy, so they may produce different results. However, in the long run, both methods are expected to converge to similar selections of optimal hyperparameters. The one-step-ahead method is much faster than backtesting because it requires fewer iterations, but it only tests the model's performance in the immediate next time step. It is recommended to backtest the final model for a more accurate multi-step performance estimate.\n",
    "\n",
    "The document compares the performance of these two methods when applied to various datasets and forecaster types. The process is outlined as follows:\n",
    "\n",
    "+ Optimal hyperparameters and lags are identified through a search using both backtesting and one-step-ahead evaluation methods. This search is performed on the validation partition, and the best configuration is stored along with the time taken to complete the search.\n",
    "\n",
    "+ Finally, the selected best configuration is evaluated on the test partition using a backtesting procedure.\n",
    "\n",
    "It is important to note that the final evaluation is consistently performed using backtesting to simulate a real-world multi-step forecasting scenario."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Results"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The results show a significant reduction in the time required to find the optimal configuration using the one-step-ahead method (top panel). However, the performance of the selected configuration on the test partition is similar for both methods (lower panel), with no clear winner. These results are consistent for both grid search and Bayesian search approaches."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-align: center;\">\n",
    "    <img src=\"../img/grid_search_benchmarck.png\" alt=\"Grid Search Results\" width=\"700\"/>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"text-align: center;\">\n",
    "    <img src=\"../img/bayesian_search_benchmarck.png\" alt=\"Grid Search Results\" width=\"700\"/>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"admonition note\" name=\"html-admonition\" style=\"background: rgba(0,184,212,.1); padding-top: 0px; padding-bottom: 6px; border-radius: 8px; border-left: 8px solid #00b8d4; border-color: #00b8d4; padding-left: 10px; padding-right: 10px;\">\n",
    "\n",
    "<p class=\"title\">\n",
    "    <i style=\"font-size: 18px; color:#00b8d4;\"></i>\n",
    "    <b style=\"color: #00b8d4;\">&#9998 Note</b>\n",
    "</p>\n",
    "\n",
    "The purpose of this analysis is to compare the time and forecasting performance of the two available evaluation methods, not to compare different forecasters.\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Libraries and data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Libraries\n",
    "# ==============================================================================\n",
    "import platform\n",
    "import psutil\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "from time import time\n",
    "from copy import copy\n",
    "import sklearn\n",
    "import skforecast\n",
    "import lightgbm\n",
    "from lightgbm import LGBMRegressor\n",
    "from sklearn.linear_model import Ridge\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from skforecast.datasets import fetch_dataset\n",
    "from skforecast.plot import set_dark_theme\n",
    "from skforecast.recursive import ForecasterRecursive\n",
    "from skforecast.direct import ForecasterDirect\n",
    "from skforecast.model_selection import TimeSeriesFold, OneStepAheadFold\n",
    "from skforecast.model_selection import grid_search_forecaster\n",
    "from skforecast.model_selection import bayesian_search_forecaster\n",
    "from skforecast.model_selection import backtesting_forecaster\n",
    "from skforecast.recursive import ForecasterRecursiveMultiSeries\n",
    "from skforecast.direct import ForecasterDirectMultiVariate\n",
    "from skforecast.model_selection import backtesting_forecaster_multiseries\n",
    "from skforecast.model_selection import grid_search_forecaster_multiseries\n",
    "from skforecast.model_selection import bayesian_search_forecaster_multiseries\n",
    "from skforecast.preprocessing import reshape_series_long_to_dict\n",
    "from skforecast.preprocessing import reshape_exog_long_to_dict\n",
    "\n",
    "# Warnings\n",
    "# ==============================================================================\n",
    "import warnings\n",
    "from skforecast.exceptions import IgnoredArgumentWarning\n",
    "warnings.filterwarnings('ignore')\n",
    "warnings.simplefilter('ignore', category=IgnoredArgumentWarning)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Python version      : 3.12.9\n",
      "scikit-learn version: 1.5.2\n",
      "skforecast version  : 0.15.0\n",
      "lightgbm version    : 4.6.0\n",
      "pandas version      : 2.2.3\n",
      "numpy version       : 1.26.4\n",
      "\n",
      "Machine type: x86_64\n",
      "Processor type: x86_64\n",
      "Platform type: Linux-5.15.0-1077-aws-x86_64-with-glibc2.31\n",
      "Operating system: Linux\n",
      "Operating system release: 5.15.0-1077-aws\n",
      "Operating system version: #84~20.04.1-Ubuntu SMP Mon Jan 20 22:14:54 UTC 2025\n",
      "Number of physical cores: 4\n",
      "Number of logical cores: 8\n"
     ]
    }
   ],
   "source": [
    "# Versions\n",
    "# ==============================================================================\n",
    "print(f\"Python version      : {platform.python_version()}\")\n",
    "print(f\"scikit-learn version: {sklearn.__version__}\")\n",
    "print(f\"skforecast version  : {skforecast.__version__}\")\n",
    "print(f\"lightgbm version    : {lightgbm.__version__}\")\n",
    "print(f\"pandas version      : {pd.__version__}\")\n",
    "print(f\"numpy version       : {np.__version__}\")\n",
    "print(\"\")\n",
    "\n",
    "# System information\n",
    "# ==============================================================================\n",
    "print(f\"Machine type: {platform.machine()}\")\n",
    "print(f\"Processor type: {platform.processor()}\")\n",
    "print(f\"Platform type: {platform.platform()}\")\n",
    "print(f\"Operating system: {platform.system()}\")\n",
    "print(f\"Operating system release: {platform.release()}\")\n",
    "print(f\"Operating system version: {platform.version()}\")\n",
    "print(f\"Number of physical cores: {psutil.cpu_count(logical=False)}\")\n",
    "print(f\"Number of logical cores: {psutil.cpu_count(logical=True)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import data\n",
    "# ==============================================================================\n",
    "data_bike = fetch_dataset('bike_sharing_extended_features', verbose=False)\n",
    "\n",
    "data_sales = fetch_dataset(name=\"items_sales\", verbose=False)\n",
    "data_sales = data_sales * 100\n",
    "data_sales['day_of_week'] = data_sales.index.dayofweek\n",
    "\n",
    "data_website = fetch_dataset(name=\"website_visits\", raw=True, verbose=False)\n",
    "data_website['date'] = pd.to_datetime(data_website['date'], format='%d/%m/%y')\n",
    "data_website = data_website.set_index('date')\n",
    "data_website = data_website.asfreq('1D')\n",
    "data_website = data_website.sort_index()\n",
    "data_website['month'] = data_website.index.month\n",
    "data_website['month_day'] = data_website.index.day\n",
    "data_website['week_day'] = data_website.index.day_of_week\n",
    "data_website = pd.get_dummies(data_website, columns=['month', 'week_day', 'month_day'], dtype='int64')\n",
    "\n",
    "data_electricity = fetch_dataset(name='vic_electricity', raw=False, verbose=False)\n",
    "data_electricity = data_electricity.drop(columns=\"Date\")\n",
    "data_electricity = (\n",
    "    data_electricity\n",
    "    .resample(rule=\"h\", closed=\"left\", label=\"right\")\n",
    "    .agg({\n",
    "        \"Demand\": \"mean\",\n",
    "        \"Temperature\": \"mean\",\n",
    "        \"Holiday\": \"mean\",\n",
    "    })\n",
    ")\n",
    "data_electricity = data_electricity.loc['2012-01-01 00:00:00': '2013-12-30 23:00:00'].copy()\n",
    "\n",
    "series_dict = pd.read_csv(\n",
    "    'https://raw.githubusercontent.com/skforecast/skforecast-datasets/main/data/demo_multi_series.csv'\n",
    ")\n",
    "exog_dict = pd.read_csv(\n",
    "    'https://raw.githubusercontent.com/skforecast/skforecast-datasets/main/data/demo_multi_series_exog.csv'\n",
    ")\n",
    "series_dict['timestamp'] = pd.to_datetime(series_dict['timestamp'])\n",
    "exog_dict['timestamp'] = pd.to_datetime(exog_dict['timestamp'])\n",
    "\n",
    "series_dict = reshape_series_long_to_dict(\n",
    "    data      = series_dict,\n",
    "    series_id = 'series_id',\n",
    "    index     = 'timestamp',\n",
    "    values    = 'value',\n",
    "    freq      = 'D'\n",
    ")\n",
    "exog_dict = reshape_exog_long_to_dict(\n",
    "    data      = exog_dict,\n",
    "    series_id = 'series_id',\n",
    "    index     = 'timestamp',\n",
    "    freq      = 'D'\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Benchmark"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Functions to compare results using backtesting and one step ahead\n",
    "# ==============================================================================\n",
    "def run_benchmark(\n",
    "    data,\n",
    "    forecaster_to_benchmark,\n",
    "    search_method = None,\n",
    "    lags_grid = None,\n",
    "    param_grid = None,\n",
    "    search_space = None,\n",
    "    end_train = None,\n",
    "    end_validation = None,\n",
    "    target = None,\n",
    "    exog_features = None,\n",
    "    steps = None,\n",
    "    metric = None\n",
    "):\n",
    "    \"\"\"\n",
    "    Compare results of grid search and bayesian search using backtesting and one-step-ahead.\n",
    "    \"\"\"\n",
    "    \n",
    "    # backtesting\n",
    "    forecaster = copy(forecaster_to_benchmark)\n",
    "    start  = time()\n",
    "    cv = TimeSeriesFold(\n",
    "            initial_train_size = len(data.loc[:end_train]),\n",
    "            steps              = steps,\n",
    "            refit              = False,\n",
    "         )\n",
    "    if search_method == 'grid_search':\n",
    "        results_1 = grid_search_forecaster(\n",
    "                        forecaster    = forecaster,\n",
    "                        y             = data.loc[:end_validation, target],\n",
    "                        exog          = data.loc[:end_validation, exog_features] if exog_features else None,\n",
    "                        cv            = cv,\n",
    "                        param_grid    = param_grid,\n",
    "                        lags_grid     = lags_grid,\n",
    "                        metric        = metric,\n",
    "                        return_best   = False,\n",
    "                        n_jobs        = 'auto',\n",
    "                        verbose       = False,\n",
    "                        show_progress = False\n",
    "                    )\n",
    "    else:\n",
    "        results_1, _ = bayesian_search_forecaster(\n",
    "                           forecaster    = forecaster,\n",
    "                           y             = data.loc[:end_validation, target],\n",
    "                           exog          = data.loc[:end_validation, exog_features] if exog_features else None,\n",
    "                           cv            = cv,\n",
    "                           search_space  = search_space,\n",
    "                           metric        = metric,\n",
    "                           n_trials      = 15,\n",
    "                           random_state  = 123,\n",
    "                           return_best   = False,\n",
    "                           n_jobs        = 'auto',\n",
    "                           verbose       = False,\n",
    "                           show_progress = False\n",
    "                       )\n",
    "\n",
    "    end = time()\n",
    "    time_1 = end - start\n",
    "    best_params = results_1.loc[0, 'params']\n",
    "    best_lags = results_1.loc[0, 'lags']\n",
    "    forecaster.set_params(best_params)\n",
    "    forecaster.set_lags(lags=best_lags)\n",
    "    cv = TimeSeriesFold(\n",
    "            initial_train_size = len(data.loc[:end_validation]),\n",
    "            steps              = steps,\n",
    "            refit              = False,\n",
    "         )\n",
    "    metric_1, _ = backtesting_forecaster(\n",
    "                      forecaster    = forecaster,\n",
    "                      y             = data.loc[:, target],\n",
    "                      exog          = data.loc[:, exog_features] if exog_features else None,\n",
    "                      cv            = cv,\n",
    "                      metric        = metric,\n",
    "                      verbose       = False,\n",
    "                      show_progress = False\n",
    "                  )\n",
    "\n",
    "    # One step ahead\n",
    "    forecaster = copy(forecaster_to_benchmark)\n",
    "    start  = time()\n",
    "    cv = OneStepAheadFold(initial_train_size = len(data.loc[:end_train]))\n",
    "    if search_method == 'grid_search':\n",
    "        results_2 = grid_search_forecaster(\n",
    "                        forecaster    = forecaster,\n",
    "                        y             = data.loc[:end_validation, target],\n",
    "                        exog          = data.loc[:end_validation, exog_features] if exog_features else None,\n",
    "                        cv            = cv,\n",
    "                        param_grid    = param_grid,\n",
    "                        lags_grid     = lags_grid,\n",
    "                        metric        = metric,\n",
    "                        return_best   = False,\n",
    "                        verbose       = False,\n",
    "                        show_progress = False\n",
    "                    )\n",
    "    else:\n",
    "        results_2, _ = bayesian_search_forecaster(\n",
    "                           forecaster    = forecaster,\n",
    "                           y             = data.loc[:end_validation, target],\n",
    "                           exog          = data.loc[:end_validation, exog_features] if exog_features else None,\n",
    "                           cv            = cv,\n",
    "                           search_space  = search_space,\n",
    "                           metric        = metric,\n",
    "                           n_trials      = 15,\n",
    "                           random_state  = 123,\n",
    "                           return_best   = False,\n",
    "                           verbose       = False,\n",
    "                           show_progress = False\n",
    "                       )\n",
    "\n",
    "    end = time()\n",
    "    time_2 = end - start\n",
    "    best_params = results_2.loc[0, 'params']\n",
    "    best_lags = results_2.loc[0, 'lags']\n",
    "    forecaster.set_params(best_params)\n",
    "    forecaster.set_lags(lags=best_lags)\n",
    "    cv = TimeSeriesFold(\n",
    "            initial_train_size = len(data.loc[:end_validation]),\n",
    "            steps              = steps,\n",
    "            refit              = False,\n",
    "         )\n",
    "    metric_2, _ = backtesting_forecaster(\n",
    "                      forecaster    = forecaster,\n",
    "                      y             = data.loc[:, target],\n",
    "                      exog          = data.loc[:, exog_features] if exog_features else None,\n",
    "                      cv            = cv,\n",
    "                      metric        = metric,\n",
    "                      verbose       = False,\n",
    "                      show_progress = False\n",
    "                  )\n",
    "\n",
    "    print(\"-----------------\")\n",
    "    print(\"Benchmark results\")\n",
    "    print(\"-----------------\")\n",
    "    print('Execution time backtesting   :', time_1)\n",
    "    print('Execution time one step ahead:', time_2)\n",
    "    print(f\"Same lags   : {np.array_equal(results_1.loc[0, 'lags'], results_2.loc[0, 'lags'])}\")\n",
    "    print(f\"Same params : {results_1.loc[0, 'params'] == results_2.loc[0, 'params']}\")\n",
    "    print(\"\")\n",
    "    print(\"Method: backtesting\")\n",
    "    print(f\"    lags   : {results_1.loc[0, 'lags']}\")\n",
    "    print(f\"    params : {results_1.loc[0, 'params']}\")\n",
    "    print(f\"    {metric}: {metric_1.loc[0, metric]}\")\n",
    "    print(\"\")\n",
    "    print(\"Method: one step ahead\")\n",
    "    print(f\"    lags   : {results_2.loc[0, 'lags']}\")\n",
    "    print(f\"    params : {results_2.loc[0, 'params']}\")\n",
    "    print(f\"    {metric}: {metric_2.loc[0, metric]}\")\n",
    "    \n",
    "    return time_1, time_2, metric_1.loc[0, metric], metric_2.loc[0, metric]\n",
    "\n",
    "\n",
    "# Functions to compare results using backtesting and one step ahead\n",
    "# ==============================================================================\n",
    "def run_benchmark_multiseries(\n",
    "    data = None,\n",
    "    forecaster_to_benchmark = None,\n",
    "    search_method = None,\n",
    "    lags_grid = None,\n",
    "    param_grid = None,\n",
    "    search_space = None,\n",
    "    end_train = None,\n",
    "    end_validation = None,\n",
    "    levels = None,\n",
    "    exog_features = None,\n",
    "    steps = None,\n",
    "    metric = None\n",
    "):\n",
    "    \"\"\"\n",
    "    Compare results of grid search using backtesting and one-step-ahead.\n",
    "    \"\"\"\n",
    "    \n",
    "    # Backtesting\n",
    "    forecaster = copy(forecaster_to_benchmark)\n",
    "    start  = time()\n",
    "    cv = TimeSeriesFold(\n",
    "                initial_train_size = len(data.loc[:end_train]),\n",
    "                steps              = steps,\n",
    "                refit              = False,\n",
    "             )\n",
    "    if search_method == 'grid_search':\n",
    "        results_1 = grid_search_forecaster_multiseries(\n",
    "                        forecaster    = forecaster,\n",
    "                        series        = data.loc[:end_validation, levels],\n",
    "                        levels        = levels,\n",
    "                        exog          = data.loc[:end_validation, exog_features] if exog_features else None,\n",
    "                        cv            = cv,\n",
    "                        param_grid    = param_grid,\n",
    "                        lags_grid     = lags_grid,\n",
    "                        metric        = metric,\n",
    "                        return_best   = False,\n",
    "                        n_jobs        = 'auto',\n",
    "                        verbose       = False,\n",
    "                        show_progress = False\n",
    "                    )\n",
    "    else:\n",
    "        results_1, _ = bayesian_search_forecaster_multiseries(\n",
    "                           forecaster    = forecaster,\n",
    "                           series        = data.loc[:end_validation, levels],\n",
    "                           exog          = data.loc[:end_validation, exog_features] if exog_features else None,\n",
    "                           levels        = levels,\n",
    "                           search_space  = search_space,\n",
    "                           cv            = cv,\n",
    "                           metric        = metric,\n",
    "                           n_trials      = 15,\n",
    "                           random_state  = 123,\n",
    "                           return_best   = False,\n",
    "                           n_jobs        = 'auto',\n",
    "                           verbose       = False,\n",
    "                           show_progress = False\n",
    "                       )\n",
    "    end = time()\n",
    "    time_1 = end - start\n",
    "    best_params = results_1.loc[0, 'params']\n",
    "    best_lags = results_1.loc[0, 'lags']\n",
    "    forecaster.set_params(best_params)\n",
    "    forecaster.set_lags(lags=best_lags)\n",
    "    cv = TimeSeriesFold(\n",
    "            initial_train_size = len(data.loc[:end_validation]),\n",
    "            steps              = steps,\n",
    "            refit              = False,\n",
    "         )\n",
    "    metric_1, _ = backtesting_forecaster_multiseries(\n",
    "                      forecaster    = forecaster,\n",
    "                      series        = data.loc[:, levels],\n",
    "                      exog          = data.loc[:, exog_features] if exog_features else None,\n",
    "                      cv            = cv,\n",
    "                      levels        = levels,\n",
    "                      metric        = metric,\n",
    "                      verbose       = False,\n",
    "                      show_progress = False\n",
    "                  )\n",
    "\n",
    "    # One step ahead\n",
    "    forecaster = copy(forecaster_to_benchmark)\n",
    "    start  = time()\n",
    "    cv = OneStepAheadFold(initial_train_size = len(data.loc[:end_train]))\n",
    "    if search_method == 'grid_search':\n",
    "        results_2 = grid_search_forecaster_multiseries(\n",
    "                        forecaster    = forecaster,\n",
    "                        series        = data.loc[:end_validation, levels],\n",
    "                        exog          = data.loc[:end_validation, exog_features] if exog_features else None,\n",
    "                        cv            = cv,\n",
    "                        levels        = levels,\n",
    "                        param_grid    = param_grid,\n",
    "                        lags_grid     = lags_grid,\n",
    "                        metric        = metric,\n",
    "                        return_best   = False,\n",
    "                        verbose       = False,\n",
    "                        show_progress = False\n",
    "                    )\n",
    "    else:\n",
    "        results_2, _ = bayesian_search_forecaster_multiseries(\n",
    "                           forecaster    = forecaster,\n",
    "                           series        = data.loc[:end_validation, levels],\n",
    "                           exog          = data.loc[:end_validation, exog_features] if exog_features else None,\n",
    "                           cv            = cv,\n",
    "                           levels        = levels,\n",
    "                           search_space  = search_space,\n",
    "                           metric        = metric,\n",
    "                           n_trials      = 15,\n",
    "                           random_state  = 123,\n",
    "                           return_best   = False,\n",
    "                           verbose       = False,\n",
    "                           show_progress = False\n",
    "                       )\n",
    "\n",
    "    end = time()\n",
    "    time_2 = end - start\n",
    "    best_params = results_2.loc[0, 'params']\n",
    "    best_lags = results_2.loc[0, 'lags']\n",
    "    forecaster.set_params(best_params)\n",
    "    forecaster.set_lags(lags=best_lags)\n",
    "    cv = TimeSeriesFold(\n",
    "            initial_train_size = len(data.loc[:end_validation]),\n",
    "            steps              = steps,\n",
    "            refit              = False,\n",
    "         )\n",
    "    metric_2, _ = backtesting_forecaster_multiseries(\n",
    "                      forecaster    = forecaster,\n",
    "                      series        = data.loc[:, levels],\n",
    "                      exog          = data.loc[:, exog_features] if exog_features else None,\n",
    "                      cv            = cv,\n",
    "                      levels        = levels,\n",
    "                      metric        = metric,\n",
    "                      verbose       = False,\n",
    "                      show_progress = False\n",
    "                  )\n",
    "\n",
    "    print(\"Benchmark results\")\n",
    "    print(\"-----------------\")\n",
    "    print('Execution time backtesting   :', time_1)\n",
    "    print('Execution time one step ahead:', time_2)\n",
    "    print(f\"Same lags   : {np.array_equal(results_1.loc[0, 'lags'], results_2.loc[0, 'lags'])}\")\n",
    "    print(f\"Same params : {results_1.loc[0, 'params'] == results_2.loc[0, 'params']}\")\n",
    "    print(\"\")\n",
    "    print(\"Method: backtesting\")\n",
    "    print(f\"    lags   : {results_1.loc[0, 'lags']}\")\n",
    "    print(f\"    params : {results_1.loc[0, 'params']}\")\n",
    "    print(f\"    {metric_1.loc[0, metric]}\")\n",
    "    print(\"\")\n",
    "    print(\"Method: one step ahead\")\n",
    "    print(f\"    lags   : {results_2.loc[0, 'lags']}\")\n",
    "    print(f\"    params : {results_2.loc[0, 'params']}\")\n",
    "    print(f\"    {metric_2.loc[0, metric]}\")\n",
    "    \n",
    "    return time_1, time_2, metric_1.loc[0, metric], metric_2.loc[0, metric]\n",
    "\n",
    "\n",
    "def summarize_results(results, metric, title, plot=True, save_plot=None, fig_size=(8, 4)):\n",
    "    \"\"\"\n",
    "    Summarize results of benchmark.\n",
    "    \"\"\"\n",
    "\n",
    "    results = pd.DataFrame(\n",
    "        results,\n",
    "        columns=[\n",
    "            \"dataset\",\n",
    "            \"forecaster\",\n",
    "            \"time_search_backtesting\",\n",
    "            \"time_search_one_step\",\n",
    "            \"metric_backtesting\",\n",
    "            \"metric_one_step\",\n",
    "        ]\n",
    "    )\n",
    "    results['ratio_speed'] = (\n",
    "        results['time_search_backtesting'] / results['time_search_one_step']\n",
    "    ).round(2)\n",
    "    results['ratio_metric'] = (\n",
    "        results['metric_backtesting'] / results['metric_one_step']\n",
    "    ).round(2)\n",
    "    results[\"dataset_forecaster\"] = (\n",
    "        results[\"dataset\"]\n",
    "        + \" \\n \"\n",
    "        + results[\"forecaster\"].str.replace(\"Forecaster\", \"\")\n",
    "    )\n",
    "    display(results)\n",
    "\n",
    "    if plot:\n",
    "        set_dark_theme()\n",
    "        fig, axs = plt.subplots(2, 1, figsize=fig_size, sharex=True)\n",
    "        results.plot.bar(\n",
    "            x='dataset_forecaster',\n",
    "            y=['time_search_backtesting', 'time_search_one_step'],\n",
    "            ax=axs[0],\n",
    "        )\n",
    "        axs[0].set_ylabel('time (s)')\n",
    "        axs[0].legend([\"backtesting\", \"one-step-ahead\"])\n",
    "        results.plot.bar(\n",
    "            x='dataset_forecaster',\n",
    "            y=['metric_backtesting', 'metric_one_step'],\n",
    "            ax=axs[1],\n",
    "            legend=False\n",
    "        )\n",
    "        axs[1].set_ylabel(f'{metric}')\n",
    "        axs[1].set_xlabel('')\n",
    "        plt.xticks(rotation=90)\n",
    "        plt.suptitle(title)\n",
    "        plt.tight_layout()\n",
    "\n",
    "        if save_plot:\n",
    "            plt.savefig(save_plot, dpi=300, bbox_inches='tight')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Grid search"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Results\n",
    "# ==============================================================================\n",
    "results_grid_search = []\n",
    "metric = 'mean_absolute_error'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------\n",
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 87.1414406299591\n",
      "Execution time one step ahead: 7.115885972976685\n",
      "Same lags   : False\n",
      "Same params : True\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [  1   2   3  23  24  25 167 168 169]\n",
      "    params : {'learning_rate': 0.1, 'max_depth': 3, 'n_estimators': 200}\n",
      "    mean_absolute_error: 58.276762590192014\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48\n",
      " 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72]\n",
      "    params : {'learning_rate': 0.1, 'max_depth': 3, 'n_estimators': 200}\n",
      "    mean_absolute_error: 64.04254202108999\n"
     ]
    }
   ],
   "source": [
    "# Dataset bike_sharing_extended_features - ForecasterRecursive\n",
    "# ==============================================================================\n",
    "end_train = '2012-03-31 23:59:00'\n",
    "end_validation = '2012-08-31 23:59:00'\n",
    "exog_features = [\n",
    "    'month_sin', 'month_cos', 'week_of_year_sin', 'week_of_year_cos', 'week_day_sin',\n",
    "    'week_day_cos', 'hour_day_sin', 'hour_day_cos', 'sunrise_hour_sin', 'sunrise_hour_cos',\n",
    "    'sunset_hour_sin', 'sunset_hour_cos', 'holiday_previous_day', 'holiday_next_day',\n",
    "    'temp_roll_mean_1_day', 'temp_roll_mean_7_day', 'temp_roll_max_1_day',\n",
    "    'temp_roll_min_1_day', 'temp_roll_max_7_day', 'temp_roll_min_7_day',\n",
    "    'temp', 'holiday'\n",
    "]\n",
    "\n",
    "forecaster = ForecasterRecursive(\n",
    "                 estimator = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                 lags      = 10\n",
    "             )\n",
    "lags_grid = [48, 72, (1, 2, 3, 23, 24, 25, 167, 168, 169)]\n",
    "\n",
    "param_grid = {\n",
    "    'n_estimators': [100, 200],\n",
    "    'max_depth': [3, 5],\n",
    "    'learning_rate': [0.01, 0.1]\n",
    "}\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark(\n",
    "    data                    = data_bike,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'grid_search',\n",
    "    lags_grid               = lags_grid,\n",
    "    param_grid              = param_grid,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    target                  = 'users',\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 24,\n",
    "    metric                  = metric\n",
    ")\n",
    "\n",
    "results_grid_search.append([\n",
    "    'bike',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------\n",
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 67.9793062210083\n",
      "Execution time one step ahead: 1.2969775199890137\n",
      "Same lags   : False\n",
      "Same params : False\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48\n",
      " 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72]\n",
      "    params : {'alpha': 112.88378916846884}\n",
      "    mean_absolute_error: 79.14111581771634\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [  1   2   3  23  24  25 167 168 169]\n",
      "    params : {'alpha': 12.742749857031322}\n",
      "    mean_absolute_error: 111.95615163625295\n"
     ]
    }
   ],
   "source": [
    "# Dataset bike_sharing_extended_features - ForecasterDirect\n",
    "# ==============================================================================\n",
    "forecaster = ForecasterDirect(\n",
    "                 estimator     = Ridge(random_state=123),\n",
    "                 transformer_y = StandardScaler(),\n",
    "                 steps         = 24,\n",
    "                 lags          = 10\n",
    "             )\n",
    "\n",
    "lags_grid = [48, 72, (1, 2, 3, 23, 24, 25, 167, 168, 169)]\n",
    "\n",
    "param_grid = {'alpha': np.logspace(-3, 3, 20)}\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark(\n",
    "    data                    = data_bike,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'grid_search',\n",
    "    lags_grid               = lags_grid,\n",
    "    param_grid              = param_grid,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    target                  = 'users',\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 24,\n",
    "    metric                  = metric\n",
    ")\n",
    "results_grid_search.append([\n",
    "    'bike',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------\n",
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 5.345601797103882\n",
      "Execution time one step ahead: 0.4459536075592041\n",
      "Same lags   : True\n",
      "Same params : False\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14]\n",
      "    params : {'alpha': 6.158482110660261}\n",
      "    mean_absolute_error: 162.11396980738706\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14]\n",
      "    params : {'alpha': 2.976351441631316}\n",
      "    mean_absolute_error: 162.3516346601722\n"
     ]
    }
   ],
   "source": [
    "# Dataset website_visits - ForecasterRecursive\n",
    "# ==============================================================================\n",
    "end_train = '2021-03-30 23:59:00'\n",
    "end_validation = '2021-06-30 23:59:00'\n",
    "exog_features = [col for col in data_website.columns if col.startswith(('month_', 'week_day_', 'month_day_'))]\n",
    "\n",
    "forecaster = ForecasterRecursive(\n",
    "                 estimator     = Ridge(random_state=123),\n",
    "                 transformer_y = StandardScaler(),\n",
    "                 lags          = 10\n",
    "             )\n",
    "\n",
    "lags_grid = [7, 14, 21, [7, 14, 21]]\n",
    "\n",
    "param_grid = {'alpha': np.logspace(-3, 3, 20)}\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark(\n",
    "    data                    = data_website,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'grid_search',\n",
    "    lags_grid               = lags_grid,\n",
    "    param_grid              = param_grid,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    target                  = 'users',\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 7,\n",
    "    metric                  = metric\n",
    ")\n",
    "results_grid_search.append([\n",
    "    'website',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------\n",
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 8.905436277389526\n",
      "Execution time one step ahead: 0.7390425205230713\n",
      "Same lags   : True\n",
      "Same params : False\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14]\n",
      "    params : {'alpha': 6.158482110660261}\n",
      "    mean_absolute_error: 277.8362513175169\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14]\n",
      "    params : {'alpha': 1.438449888287663}\n",
      "    mean_absolute_error: 236.28560218972729\n"
     ]
    }
   ],
   "source": [
    "# Dataset website_visits - ForecasterDirect\n",
    "# ==============================================================================\n",
    "forecaster = ForecasterDirect(\n",
    "                 estimator = Ridge(random_state=123),\n",
    "                 steps     = 24,\n",
    "                 lags      = 10\n",
    "             )\n",
    "\n",
    "lags_grid = [7, 14, 21, [7, 14, 21]]\n",
    "\n",
    "param_grid = {'alpha': np.logspace(-3, 3, 20)}\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark(\n",
    "    data                    = data_website,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'grid_search',\n",
    "    lags_grid               = lags_grid,\n",
    "    param_grid              = param_grid,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    target                  = 'users',\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 24,\n",
    "    metric                  = metric\n",
    ")\n",
    "results_grid_search.append([\n",
    "    'website',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------\n",
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 83.48313307762146\n",
      "Execution time one step ahead: 6.249357223510742\n",
      "Same lags   : False\n",
      "Same params : True\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [  1   2   3  23  24  25 167 168 169]\n",
      "    params : {'learning_rate': 0.1, 'max_depth': 5, 'n_estimators': 200}\n",
      "    mean_absolute_error: 194.83553235066182\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48\n",
      " 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72]\n",
      "    params : {'learning_rate': 0.1, 'max_depth': 5, 'n_estimators': 200}\n",
      "    mean_absolute_error: 188.8782299908785\n"
     ]
    }
   ],
   "source": [
    "# Dataset vic_electricity - ForecasterRecursive\n",
    "# ==============================================================================\n",
    "end_train = '2013-06-30 23:59:00'\n",
    "end_validation = '2013-11-30 23:59:00'\n",
    "exog_features = ['Temperature', 'Holiday']\n",
    "\n",
    "forecaster = ForecasterRecursive(\n",
    "                 estimator = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                 lags      = 10\n",
    "             )\n",
    "\n",
    "lags_grid = [48, 72, (1, 2, 3, 23, 24, 25, 167, 168, 169)]\n",
    "\n",
    "param_grid = {\n",
    "    'n_estimators': [100, 200],\n",
    "    'max_depth': [3, 5],\n",
    "    'learning_rate': [0.01, 0.1]\n",
    "}\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark(\n",
    "    data                    = data_electricity,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'grid_search',\n",
    "    lags_grid               = lags_grid,\n",
    "    param_grid              = param_grid,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    target                  = 'Demand',\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 24,\n",
    "    metric                  = metric\n",
    ")\n",
    "results_grid_search.append([\n",
    "    'electricity',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------\n",
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 62.373592138290405\n",
      "Execution time one step ahead: 1.0504238605499268\n",
      "Same lags   : True\n",
      "Same params : False\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48\n",
      " 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72]\n",
      "    params : {'alpha': 6.158482110660261}\n",
      "    mean_absolute_error: 304.22332781257694\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48\n",
      " 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72]\n",
      "    params : {'alpha': 1.438449888287663}\n",
      "    mean_absolute_error: 301.7070971763055\n"
     ]
    }
   ],
   "source": [
    "# Dataset vic_electricity - ForecasterDirect\n",
    "# ==============================================================================\n",
    "forecaster = ForecasterDirect(\n",
    "                 estimator     = Ridge(random_state=123),\n",
    "                 transformer_y = StandardScaler(),\n",
    "                 steps         = 24,\n",
    "                 lags          = 10\n",
    "             )\n",
    "\n",
    "lags_grid = [48, 72, (1, 2, 3, 23, 24, 25, 167, 168, 169)]\n",
    "\n",
    "param_grid = {'alpha': np.logspace(-3, 3, 20)}\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark(\n",
    "    data                    = data_electricity,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'grid_search',\n",
    "    lags_grid               = lags_grid,\n",
    "    param_grid              = param_grid,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    target                  = 'Demand',\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 24,\n",
    "    metric                  = metric\n",
    ")\n",
    "results_grid_search.append([\n",
    "    'electricity',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 1.6175434589385986\n",
      "Execution time one step ahead: 0.9103469848632812\n",
      "Same lags   : False\n",
      "Same params : False\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]\n",
      "    params : {'max_depth': 7, 'n_estimators': 200}\n",
      "    137.16940500432474\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48]\n",
      "    params : {'max_depth': 3, 'n_estimators': 50}\n",
      "    134.76669158338447\n"
     ]
    }
   ],
   "source": [
    "# Dataset sales - ForecasterRecursiveMultiSeries\n",
    "# ==============================================================================\n",
    "end_train = '2014-05-15 23:59:00'\n",
    "end_validation = '2014-07-15 23:59:00'\n",
    "levels = ['item_1', 'item_2', 'item_3']\n",
    "exog_features = ['day_of_week']\n",
    "\n",
    "forecaster = ForecasterRecursiveMultiSeries(\n",
    "                 estimator          = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                 lags               = 24,\n",
    "                 encoding           = \"ordinal\",\n",
    "                 transformer_series = None,\n",
    "                 transformer_exog   = None,\n",
    "                 weight_func        = None,\n",
    "                 series_weights     = None,\n",
    "                 differentiation    = None,\n",
    "                 dropna_from_series = False,\n",
    "                 fit_kwargs         = None,\n",
    "                 forecaster_id      = None\n",
    "             )\n",
    "\n",
    "lags_grid = {\n",
    "    '24 lags': 24,\n",
    "    '48 lags': 48\n",
    "}\n",
    "\n",
    "param_grid = {\n",
    "    'n_estimators': [50, 200],\n",
    "    'max_depth': [3, 7]\n",
    "}\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark_multiseries(\n",
    "    data                    = data_sales,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'grid_search',\n",
    "    lags_grid               = lags_grid,\n",
    "    param_grid              = param_grid,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    levels                  = levels,\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 36,\n",
    "    metric                  = metric\n",
    ")\n",
    "results_grid_search.append([\n",
    "    'sales',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 6.571660757064819\n",
      "Execution time one step ahead: 1.1719706058502197\n",
      "Same lags   : False\n",
      "Same params : True\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]\n",
      "    params : {'max_depth': 7, 'n_estimators': 50}\n",
      "    100.16441146410313\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48]\n",
      "    params : {'max_depth': 7, 'n_estimators': 50}\n",
      "    95.20010578089475\n"
     ]
    }
   ],
   "source": [
    "# Dataset sales - ForecasterDirectMultiVariate\n",
    "# ==============================================================================\n",
    "forecaster = ForecasterDirectMultiVariate(\n",
    "                 estimator          = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                 lags               = 24,\n",
    "                 steps              = 5,\n",
    "                 level              = 'item_1',\n",
    "                 transformer_series = None,\n",
    "                 transformer_exog   = None,\n",
    "                 weight_func        = None,\n",
    "                 fit_kwargs         = None,\n",
    "                 forecaster_id      = None\n",
    "             )\n",
    "\n",
    "lags_grid = {\n",
    "    '24 lags': 24,\n",
    "    '48 lags': 48\n",
    "}\n",
    "\n",
    "param_grid = {\n",
    "    'n_estimators': [50, 200],\n",
    "    'max_depth': [3, 7]\n",
    "}\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark_multiseries(\n",
    "    data                    = data_sales,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'grid_search',\n",
    "    lags_grid               = lags_grid,\n",
    "    param_grid              = param_grid,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    levels                  = levels,\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 5,\n",
    "    metric                  = metric\n",
    ")\n",
    "\n",
    "results_grid_search.append([\n",
    "    'sales',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 1.8693697452545166\n",
      "Execution time one step ahead: 0.3610079288482666\n",
      "Same lags   : False\n",
      "Same params : False\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [1 2 3 4 5 6 7]\n",
      "    params : {'max_depth': 3, 'n_estimators': 50}\n",
      "    180.46141171905165\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14]\n",
      "    params : {'max_depth': 7, 'n_estimators': 50}\n",
      "    164.23659500870002\n"
     ]
    }
   ],
   "source": [
    "# Dataset series_dict - ForecasterRecursiveMultiSeries\n",
    "# ==============================================================================\n",
    "end_train = '2016-05-31 23:59:00'\n",
    "end_validation = '2016-07-31 23:59:00'\n",
    "levels = ['id_1000', 'id_1001', 'id_1002', 'id_1003', 'id_1004']\n",
    "series_dict_train = {k: v.loc[: end_train,] for k, v in series_dict.items()}\n",
    "exog_dict_train   = {k: v.loc[: end_train,] for k, v in exog_dict.items()}\n",
    "series_dict_test  = {k: v.loc[end_train:,] for k, v in series_dict.items()}\n",
    "exog_dict_test    = {k: v.loc[end_train:,] for k, v in exog_dict.items()}\n",
    "\n",
    "forecaster_to_benchmark = ForecasterRecursiveMultiSeries(\n",
    "                              estimator          = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                              lags               = 24,\n",
    "                              encoding           = \"ordinal\",\n",
    "                              transformer_series = None,\n",
    "                              transformer_exog   = None,\n",
    "                              weight_func        = None,\n",
    "                              series_weights     = None,\n",
    "                              differentiation    = None,\n",
    "                              dropna_from_series = False,\n",
    "                              fit_kwargs         = None,\n",
    "                              forecaster_id      = None\n",
    "                          )\n",
    "lags_grid = [7, 14]\n",
    "param_grid = {\n",
    "    'n_estimators': [50, 200],\n",
    "    'max_depth': [3, 7]\n",
    "}\n",
    "\n",
    "# Backtesting\n",
    "forecaster = copy(forecaster_to_benchmark)\n",
    "start  = time()\n",
    "cv = TimeSeriesFold(\n",
    "        initial_train_size = 100,\n",
    "        steps              = 24,\n",
    "        refit              = False\n",
    "     )\n",
    "results_1 = grid_search_forecaster_multiseries(\n",
    "                forecaster        = forecaster,\n",
    "                series            = {k: v.loc[: end_validation,] for k, v in series_dict.items()},\n",
    "                exog              = {k: v.loc[: end_validation,] for k, v in exog_dict.items()},\n",
    "                cv                = cv,\n",
    "                param_grid        = param_grid,\n",
    "                lags_grid         = lags_grid,\n",
    "                metric            = metric,\n",
    "                return_best       = False,\n",
    "                n_jobs            = 'auto',\n",
    "                verbose           = False,\n",
    "                show_progress     = False,\n",
    "                suppress_warnings = True\n",
    "            )\n",
    "end = time()\n",
    "time_1 = end - start\n",
    "best_params = results_1.loc[0, 'params']\n",
    "best_lags = results_1.loc[0, 'lags']\n",
    "forecaster.set_params(best_params)\n",
    "forecaster.set_lags(lags=best_lags)\n",
    "cv = TimeSeriesFold(\n",
    "        initial_train_size = 213,\n",
    "        steps              = 24,\n",
    "        refit              = False\n",
    "     )\n",
    "metric_1, pred_1 = backtesting_forecaster_multiseries(\n",
    "                       forecaster        = forecaster,\n",
    "                       series            = series_dict,\n",
    "                       exog              = exog_dict,\n",
    "                       cv                = cv,\n",
    "                       levels            = levels,\n",
    "                       metric            = metric,\n",
    "                       verbose           = False,\n",
    "                       show_progress     = False,\n",
    "                       suppress_warnings = True\n",
    "                   )\n",
    "\n",
    "# One step ahead\n",
    "forecaster = copy(forecaster_to_benchmark)\n",
    "start  = time()\n",
    "cv = OneStepAheadFold(initial_train_size = 100)\n",
    "results_2 = grid_search_forecaster_multiseries(\n",
    "                forecaster        = forecaster,\n",
    "                series            = {k: v.loc[: end_validation,] for k, v in series_dict.items()},\n",
    "                exog              = {k: v.loc[: end_validation,] for k, v in exog_dict.items()},\n",
    "                cv                = cv,\n",
    "                levels            = levels,\n",
    "                param_grid        = param_grid,\n",
    "                lags_grid         = lags_grid,\n",
    "                metric            = metric,\n",
    "                return_best       = False,\n",
    "                verbose           = False,\n",
    "                show_progress     = False,\n",
    "                suppress_warnings = True\n",
    "            )\n",
    "end = time()\n",
    "time_2 = end - start\n",
    "best_params = results_2.loc[0, 'params']\n",
    "best_lags = results_2.loc[0, 'lags']\n",
    "forecaster.set_params(best_params)\n",
    "forecaster.set_lags(lags=best_lags)\n",
    "cv = TimeSeriesFold(\n",
    "        initial_train_size = 213,\n",
    "        steps              = 24,\n",
    "        refit              = False\n",
    "     )\n",
    "metric_2, pred_2 = backtesting_forecaster_multiseries(\n",
    "                       forecaster        = forecaster,\n",
    "                       series            = series_dict,\n",
    "                       exog              = exog_dict,\n",
    "                       cv                = cv,\n",
    "                       levels            = levels,\n",
    "                       metric            = metric,\n",
    "                       verbose           = False,\n",
    "                       show_progress     = False,\n",
    "                       suppress_warnings = True\n",
    "                   )\n",
    "\n",
    "print(\"Benchmark results\")\n",
    "print(\"-----------------\")\n",
    "print('Execution time backtesting   :', time_1)\n",
    "print('Execution time one step ahead:', time_2)\n",
    "print(f\"Same lags   : {np.array_equal(results_1.loc[0, 'lags'], results_2.loc[0, 'lags'])}\")\n",
    "print(f\"Same params : {results_1.loc[0, 'params'] == results_2.loc[0, 'params']}\")\n",
    "print(\"\")\n",
    "print(\"Method: backtesting\")\n",
    "print(f\"    lags   : {results_1.loc[0, 'lags']}\")\n",
    "print(f\"    params : {results_1.loc[0, 'params']}\")\n",
    "print(f\"    {metric_1.loc[0, metric]}\")\n",
    "print(\"\")\n",
    "print(\"Method: one step ahead\")\n",
    "print(f\"    lags   : {results_2.loc[0, 'lags']}\")\n",
    "print(f\"    params : {results_2.loc[0, 'params']}\")\n",
    "print(f\"    {metric_2.loc[0, metric]}\")\n",
    "\n",
    "results_grid_search.append([\n",
    "    'series_dict',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1.loc[0, metric],\n",
    "    metric_2.loc[0, metric],\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "index",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "dataset",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "forecaster",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "time_search_backtesting",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "time_search_one_step",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "metric_backtesting",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "metric_one_step",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "ratio_speed",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "ratio_metric",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "dataset_forecaster",
         "rawType": "object",
         "type": "string"
        }
       ],
       "conversionMethod": "pd.DataFrame",
       "ref": "e9ea60f7-5609-477e-b8d5-baea4b3b501f",
       "rows": [
        [
         "0",
         "bike",
         "ForecasterRecursive",
         "87.1414406299591",
         "7.115885972976685",
         "58.276762590192014",
         "64.04254202108999",
         "12.25",
         "0.91",
         "bike \n Recursive"
        ],
        [
         "1",
         "bike",
         "ForecasterDirect",
         "67.9793062210083",
         "1.2969775199890137",
         "79.14111581771634",
         "111.95615163625295",
         "52.41",
         "0.71",
         "bike \n Direct"
        ],
        [
         "2",
         "website",
         "ForecasterRecursive",
         "5.345601797103882",
         "0.4459536075592041",
         "162.11396980738706",
         "162.3516346601722",
         "11.99",
         "1.0",
         "website \n Recursive"
        ],
        [
         "3",
         "website",
         "ForecasterDirect",
         "8.905436277389526",
         "0.7390425205230713",
         "277.8362513175169",
         "236.28560218972729",
         "12.05",
         "1.18",
         "website \n Direct"
        ],
        [
         "4",
         "electricity",
         "ForecasterRecursive",
         "83.48313307762146",
         "6.249357223510742",
         "194.83553235066182",
         "188.8782299908785",
         "13.36",
         "1.03",
         "electricity \n Recursive"
        ],
        [
         "5",
         "electricity",
         "ForecasterDirect",
         "62.373592138290405",
         "1.0504238605499268",
         "304.22332781257694",
         "301.7070971763055",
         "59.38",
         "1.01",
         "electricity \n Direct"
        ],
        [
         "6",
         "sales",
         "ForecasterRecursiveMultiSeries",
         "1.6175434589385986",
         "0.9103469848632812",
         "137.16940500432474",
         "134.76669158338447",
         "1.78",
         "1.02",
         "sales \n RecursiveMultiSeries"
        ],
        [
         "7",
         "sales",
         "ForecasterDirectMultiVariate",
         "6.571660757064819",
         "1.1719706058502197",
         "100.16441146410313",
         "95.20010578089475",
         "5.61",
         "1.05",
         "sales \n DirectMultiVariate"
        ],
        [
         "8",
         "series_dict",
         "ForecasterRecursiveMultiSeries",
         "1.8693697452545166",
         "0.3610079288482666",
         "180.46141171905165",
         "164.23659500870002",
         "5.18",
         "1.1",
         "series_dict \n RecursiveMultiSeries"
        ]
       ],
       "shape": {
        "columns": 9,
        "rows": 9
       }
      },
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>dataset</th>\n",
       "      <th>forecaster</th>\n",
       "      <th>time_search_backtesting</th>\n",
       "      <th>time_search_one_step</th>\n",
       "      <th>metric_backtesting</th>\n",
       "      <th>metric_one_step</th>\n",
       "      <th>ratio_speed</th>\n",
       "      <th>ratio_metric</th>\n",
       "      <th>dataset_forecaster</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>bike</td>\n",
       "      <td>ForecasterRecursive</td>\n",
       "      <td>87.141441</td>\n",
       "      <td>7.115886</td>\n",
       "      <td>58.276763</td>\n",
       "      <td>64.042542</td>\n",
       "      <td>12.25</td>\n",
       "      <td>0.91</td>\n",
       "      <td>bike \\n Recursive</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>bike</td>\n",
       "      <td>ForecasterDirect</td>\n",
       "      <td>67.979306</td>\n",
       "      <td>1.296978</td>\n",
       "      <td>79.141116</td>\n",
       "      <td>111.956152</td>\n",
       "      <td>52.41</td>\n",
       "      <td>0.71</td>\n",
       "      <td>bike \\n Direct</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>website</td>\n",
       "      <td>ForecasterRecursive</td>\n",
       "      <td>5.345602</td>\n",
       "      <td>0.445954</td>\n",
       "      <td>162.113970</td>\n",
       "      <td>162.351635</td>\n",
       "      <td>11.99</td>\n",
       "      <td>1.00</td>\n",
       "      <td>website \\n Recursive</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>website</td>\n",
       "      <td>ForecasterDirect</td>\n",
       "      <td>8.905436</td>\n",
       "      <td>0.739043</td>\n",
       "      <td>277.836251</td>\n",
       "      <td>236.285602</td>\n",
       "      <td>12.05</td>\n",
       "      <td>1.18</td>\n",
       "      <td>website \\n Direct</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>electricity</td>\n",
       "      <td>ForecasterRecursive</td>\n",
       "      <td>83.483133</td>\n",
       "      <td>6.249357</td>\n",
       "      <td>194.835532</td>\n",
       "      <td>188.878230</td>\n",
       "      <td>13.36</td>\n",
       "      <td>1.03</td>\n",
       "      <td>electricity \\n Recursive</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>electricity</td>\n",
       "      <td>ForecasterDirect</td>\n",
       "      <td>62.373592</td>\n",
       "      <td>1.050424</td>\n",
       "      <td>304.223328</td>\n",
       "      <td>301.707097</td>\n",
       "      <td>59.38</td>\n",
       "      <td>1.01</td>\n",
       "      <td>electricity \\n Direct</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>sales</td>\n",
       "      <td>ForecasterRecursiveMultiSeries</td>\n",
       "      <td>1.617543</td>\n",
       "      <td>0.910347</td>\n",
       "      <td>137.169405</td>\n",
       "      <td>134.766692</td>\n",
       "      <td>1.78</td>\n",
       "      <td>1.02</td>\n",
       "      <td>sales \\n RecursiveMultiSeries</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>sales</td>\n",
       "      <td>ForecasterDirectMultiVariate</td>\n",
       "      <td>6.571661</td>\n",
       "      <td>1.171971</td>\n",
       "      <td>100.164411</td>\n",
       "      <td>95.200106</td>\n",
       "      <td>5.61</td>\n",
       "      <td>1.05</td>\n",
       "      <td>sales \\n DirectMultiVariate</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>series_dict</td>\n",
       "      <td>ForecasterRecursiveMultiSeries</td>\n",
       "      <td>1.869370</td>\n",
       "      <td>0.361008</td>\n",
       "      <td>180.461412</td>\n",
       "      <td>164.236595</td>\n",
       "      <td>5.18</td>\n",
       "      <td>1.10</td>\n",
       "      <td>series_dict \\n RecursiveMultiSeries</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       dataset                      forecaster  time_search_backtesting  \\\n",
       "0         bike             ForecasterRecursive                87.141441   \n",
       "1         bike                ForecasterDirect                67.979306   \n",
       "2      website             ForecasterRecursive                 5.345602   \n",
       "3      website                ForecasterDirect                 8.905436   \n",
       "4  electricity             ForecasterRecursive                83.483133   \n",
       "5  electricity                ForecasterDirect                62.373592   \n",
       "6        sales  ForecasterRecursiveMultiSeries                 1.617543   \n",
       "7        sales    ForecasterDirectMultiVariate                 6.571661   \n",
       "8  series_dict  ForecasterRecursiveMultiSeries                 1.869370   \n",
       "\n",
       "   time_search_one_step  metric_backtesting  metric_one_step  ratio_speed  \\\n",
       "0              7.115886           58.276763        64.042542        12.25   \n",
       "1              1.296978           79.141116       111.956152        52.41   \n",
       "2              0.445954          162.113970       162.351635        11.99   \n",
       "3              0.739043          277.836251       236.285602        12.05   \n",
       "4              6.249357          194.835532       188.878230        13.36   \n",
       "5              1.050424          304.223328       301.707097        59.38   \n",
       "6              0.910347          137.169405       134.766692         1.78   \n",
       "7              1.171971          100.164411        95.200106         5.61   \n",
       "8              0.361008          180.461412       164.236595         5.18   \n",
       "\n",
       "   ratio_metric                   dataset_forecaster  \n",
       "0          0.91                    bike \\n Recursive  \n",
       "1          0.71                       bike \\n Direct  \n",
       "2          1.00                 website \\n Recursive  \n",
       "3          1.18                    website \\n Direct  \n",
       "4          1.03             electricity \\n Recursive  \n",
       "5          1.01                electricity \\n Direct  \n",
       "6          1.02        sales \\n RecursiveMultiSeries  \n",
       "7          1.05          sales \\n DirectMultiVariate  \n",
       "8          1.10  series_dict \\n RecursiveMultiSeries  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxYAAAJRCAYAAADYlCHHAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAACr3ElEQVR4nOzdZVRbSxcG4DfBtUALNeotdXd3d3en3lt3d3d3d3d36u6FokULFCsuId8P2rT50HICScj7rHXXLUdmdjYHyM6ZmSOCVWUpiIiIiIiIBBArOwAiIiIiIlJ/LCyIiIiIiEgwFhZERERERCQYCwsiIiIiIhKMhQUREREREQnGwoKIiIiIiARjYUFERERERIKxsCAiIiIiIsFYWBARERERkWAsLIgUaO2CcXh2ZVeqx1nnsYL324vo1q5xJkSVudYuGAfHxyeUHQYAYOLwnvB+e1EpfZ/atQR3Tm3K9H69317E4mnDMr3ff5GVr3/KeMr62UrJsyu7sHbBOGWHQaR02soOgEgV5MuTE8P7dUC9mhWRxyoHAMDD2xePX37AwVPX8MXRTbkBEilQTksL9OncHNfuPsUnB9cM66djy/rIbpENuw5fyLA+SDH+G9wVji4euHb3qbJDISI1xsKCNF6TulWxbcUUxMVJcObqfXx2cEW8NB5FC1qjVeNa6Ne1Jaq3toWXj3+qbU1esBFikSgToqa0WLfzODbtOaXsMFROTksLTBzeCx7efhlaWHRoWR8liuZPVFh4evuhULVOiI2TZFjf9G/GDO6KS7ces7AgIkFYWJBGK2CdC1uXT4antx+6DZsFvx9BcvsXr9+HAd1aQxovTbEdA309REZFIy6LvlHS09VBTGwcpNKU86BqJJJ4SCTxyg6DkhAdE6vsEIiISME4x4I02sgBnWFkaIDxc9cnKiqAhDemu49ehLfvD9m233MICljnwsFNc/H10XFsXjpJtu//51iYmhhh7YJxsLc7hi92R7Fu4ThkMzFKU3za2lqYMKwHHl7YDpdnp/Hx3mGc27sc9WpUkDuuaEFr7Fg5DZ/uH4HLs9O4engNmtWvJneMmakx5owfhNsnN8Lx8Qk4PDyOQ5vmoZRNQbnjalYpA++3F9G+eV1MGdUHr27sg/PTUzAxNgQAVCxjg4Ob5uLzg6NwenISt05swOBebRPFnsvKAnvWzoTj4xP4cOcQ5owfBLE49V853m8vYuLwnom2//8Y5rTkJqk5Fr/nILRoWAN3Tm2C6/MzuHt6MxrUqpSoz5pVyuDq4TVweXYajy/uQJ/OLf553kbZkkVwYf8KOD89haeXd6FvlxZy+3W0tTF5RG9cO7IW9nbH4PTkJM7uWYZaVcomakskEmFwr7a4fXIjXJ6dxoc7h3B48zyUK1U0xRjG2naD5+vzGNSjDWpWKYNrR9YCANYtGAfvtxcTzXeoWMYGhzfPg73dMTg/OYXTu5aiaoWScm0aGRpg/mRbPLuyC67Pz+D9nYM4tm0BypYoAiBhHHzTelWRL09OWR+/fzaSmmPx++cqLdeNeTYTbFg0AQ4Pj8t+pkrZFEx13ka5UkXh/fYiurZtlGhf/ZoV4f32IprUrZqm15eSMsUL49CmeXB4eByOj0/g+PZFqFS2uNwx3do1hvfbi6haoSTmThyMD3cOwenJSexeMwMW5qaJ2mxYuzLO7lkGpycn8fXRcRzYOAc2RfKnGgsAFMqfGztXTcfbWwfg8uw0Xl7fi63LJst+pr3fXoSRoQG6/4rJ++1FuZ+1XFYWWDNvDN7dPiD7eenRvolcH79/b7RrVgfT/uuLt7cOwOnJSexbNwt5cuZIU5zNG1THgY1z8PrGPrg+P4PHF3dg3JDuyf7eKFY4H07uXAznJ6fw6sY+jBzQKdExujramDSiFx5d2A7X52fw8toezBo3ALo68p+rdm/fGCd2LML7Owfh+vwM7p3ejH5dWybZ71jbbnh5fS+cn5zCyZ2L0/x9INIEvGNBGq1JvapwcffGm49f/+k8LS0tHNkyH8/ffsGCNXsRGRWd7LF7185CtYolcfDUNTi6eKBFo5pYt2B8mvqZOLwX/hvUBUfO3sDbj44wNjJA+dLFULZEETx4+hYAYFMkP87vW47vfoHYvPcUIiKj0LZpXexZOxO2E5fKhjbkt86F5g2r49LNR3D39oWlhRn6dGmB07uXokGnUfD1D5Tre9zQHoiNjcW2A2ehp6OD2Ng41KtRAfs3zIHfj0DsPnIBfj+CUKxwPjStVxW7j/x5sy0Wi3FkywK8+eCABWv2oG71ChjevyPcPH1w4OTVf8q1kNwkp1rFUmjZqCb2n7iCsIhIDO7ZFrtWT0fVFoMQFBIKIOHN4eHN8+H3Iwirtx6BWEuM8cN6IDAoJM0xZjM1xqFNc3HxxkOcu/oAbZvVwfJZoxAbG4dj528BAEyMDdGzY1Ocu/YAh89ch7GRAXp2aIYjW+ejdZ+JckOV1swbg+7tm+D2w5c4cvYGtLW0UL1SaVQuWxzvPzslGcOUUX0wZnBXTFm0GUfO3EAOCzOs2HwIU0b1wcFT1/Ds9ScAwMt3XwAAtauWw6HN8/DhixPWbD+KeKkU3ds1wYkdi9Fx0FS8/egIAFg+ayRaN6mNvccuwdHFA+ZmJqhWoRSKFrbGB3tnbNh1AqbGhshtlQNzVyUUFBGRUSnmKy3XjUgkwv4Ns1GhtA0OnLwCJzdPNG9QA+sXpv4z9f6zE9w8fNC2WR2cvHhHbl/75nURFBKKe09ep+n1JcemSH6c3bsMoWER2LLvNOLiJOjTpQVO7VqCzoOnJ/pds2jqMAT/DMOa7UeRL09O2PZuhyXThmP41BWyYzq3boj1C8fh3uM3WLxuHwwM9NCvayuc27sczXqMhae3X7Lx6Ghr48iWBdDV1cGeY5fg/yMIuayyo0m9qjA1MUJoWARGz1iNVXP/w9uPX3Ho9HUAwDdPHwBADgszXDqwClIpsPfYZQQEhaBR7cpYM38sjI0NEw1zG2PbDVIpsHnfaeQwzwbb3u1wfPtCNO0+FlHRMSl+f7q1a4yIiCjsOHQe4RGRqF2tPKaM6gMTY0MsXLtX7thspsY4snk+rtx5jIs3HqJ1k9qYNW4gvjh+w91HrwAkXCv71s9GtYqlcOj0dTi6eqBk0QIY0rs9ChfIi0HjF8va69e1Fb46u+PG/eeQxEnQtH41LJs5EmKxCPuOX5EdN3lkb4wf2gO37F7gzsOXKFuiCI5uXQBdbb6dIgJYWJAGMzYyQG6r7Lh650mifaYmRtDW0pJ9HREZJfdHUV9PF5duPsLSjQdS7KN5g+qoWaUMFq7dg637zwIA9p+8ilM7F6d43m9N6lbB7YevMGXh5mSPWTh5CLx8/NGq9wTExMYBAPYdv4Lz+5Zj5rgBssLC3tENddoPlxvOdOryXTw4uxU9OzTFup3H5drV09VBy17jZa9bLBZj+axR8PsRiKbdx+JnaHiyMRno6+HCdTtZmwdPXcP1o+vQs0NThRUWaclNcooWyocGnUbim+d3AMDjFx9w++RGdGhRD3uPXwYATBrRC/Hx8Wg/YIqs6Lp44yHun9mS5n5yW2XHvFW7sOPQeQAJebh8aBWmj+mHU5fvIi5OguCfYajeyhaxcXGy8w6fuYEHZ7diUI82mDh/IwCgVpWy6N6+CXYduYA5K3bKjt1+8Fyy/c8ZPwhD+rTD+LnrZW+kfwQG486jVwl3o97b48yVe3LnLJs1Eo9fvEfvUfNk2w6duoa7pzdj6qi+6DliDgCgcd0qOHLmOhas2SM7bgvOyP794Olb+PgFIpupcaI+kpOW66ZFwxqoUr4kZq/YIStm95+4imPbFqapjws37DC8X0dkMzFCyK9rWEdbGy0a1cTV249lwxlTe33JmTqqD7S1tdFh4FS4e/kCAE5eugO7c9swa9xAdLadLnd8UMhP9Bg+R/a1SCzC4J5tYWJsiNCwCBga6GPh1KE4cvaG3LV+4sId2J3fmlA0pvAzYFMkHwpY58KQSUtx+dZj2fa1O47J/n3myj0snzUS37x8E32vpo3uC7FYjMZd/5MV3QdPXcOWpZMwcXhPHDp1Te53o1k2E9TvOBLhEZEAgA/2ztixchp6d2qO3UdTvtM3avoqubYOnrqG4JBQ9O/WCss3HZT9fgMSfrb+m7kGpy/fBQAcPXsTz6/uRs8OTWWFRceW9VG3enl0HjwDz99+lp1r7+SOFbNHoUr5Enj5zh4A0HnwdLm+9x6/jMOb52Fonw6ywsLC3BQjB3TGzQcv0H/MAtmxU0f3xVjbbim+NiJNwaFQpLFMjBKGAYRHJP4U9fSuJfh477DsvwHdWyc6Ji1vkBvVqYLY2DjsP/Hn2Pj4eOw5dilNMYaEhqN4kfwolD93kvvNTI1Ru1o5XLzxEMZGhrAwM5X9d+/xGxQpkBe5rCwAQG6OhFgshnk2E0RERMHZzQtlSyYe3nHy4h25P7RlShRGAetc2Hn4QopFxW8HTsnn59mbT8hvnStNrzstUstNSuyevZUVFQDwxdENP0PDZfGJxWLUrV4B1+4+lbuT4+bhI3vTkhaxsXE4eOran6/jEr62zG6OciUThi/Fx8fLigqRSAQzU2Noa2nh3Wcnue9L6ya1EB8fjzXbjqbar0gkwuJpwzC4V1v8N3NNok/nk1OmeGEUKZAXZ6/el7uWDA308fD5O1SvVBqiX4sT/AwNR8WyxZHT0iLN+UiL1K6bhrUrISY2FkfO3JBtk0ql2PerIEzNhet20NXRQavGtWTb6tesCDNTY1y48VC2LT2vTywWo37Nirh+96msqAAAvx9BOHv1PqpVLAljIwO5c37fIfjt2etP0NbWgnVuKwBAvRoVYGZqjHNXH8h9T+Lj4/Hmw1fUqlouxZh+hkYAABrUqgQDfb00v5bfWjWphZsPXkAkEsn/fnnyBtlMjBP97jh16Y6sqACASzcf4btfABrVqZxqX3//vjEyNICFmSmevfkEQwN9FC1kLXdsWHiErKgAEn623n78igJ/XSttm9aGo6snnNw85WJ/9OIdAMjl7u++TYwTfpc+efURBfPllg0Zq1e9AvR0dbDn/wqknYfPp/raiDQF71iQxgr79cfPyFA/0b4pCzfD2MgAObKbYfOSSYn2x8bGyc27SI51bkv4/QhKNATE2c0rTTGu3HIYe9fNwqMLO/DF0Q33Hr/GqUt3ZcvfFsyfG2KxGFNH98XU0X2TbCOHuRm++wVCJBLBtnc79O/WCvnz5IS29p87MkEhPxOd9/cbIwAo+OsPtoPTt1TjjoyKRmCQfJshP8Ngns0k1XPTKrXcpCSpFb5CQsNgZmoMAMhhkQ0GBnpw8/BJdJxrEtuS4+sfmGiYnMs3bwBAvjxWeP3BAQDQtW0jDOvbAUULWUNXR0d27N/FTwHr3PjuH4jgn2Gp9tulTUMYGxli6qLNOHftQZrjLVQgDwBgw6IJyR5jamyIkNBwLFq3D+sWjMPLa3vw/osz7jx8iZMX7yS6bv5FWq4b69xW8PMPSpTXpL5XSfn81Q2OLh5o17wujp67CQBo17wuAgJD8PD5O9lx6Xl92c0TirCkfr4dXT2gpaWFPLks8dXZXbb9/6/FkNCE72+2X9di4V/fk1O7liTZ5+8iX19PV/YG+Df/gGB4ePti24GzGN6vIzq1bIBnbz7hxv1nOH35HkLDIpJ9LQmvJxvMTI3Rt0uLRHOD/j7mb67u3omOcfPwQb48OQEAhgb6cr9zJfHxsu+5TZH8mDqqD2pXLQfT/5uHZmIs/7WPb0CifoJDw1HSppDs60L588CmSH58vHc4ydhzWPyJvWqFkpg0vBcqly8BQwP5vwmmxglDxn4Xe///GgODfsru5hBpOhYWpLFCwyLw3S8AxYsWSLTv9zho6zxWSZ4bExubKSskPXv9CbXaDEHzhtVRv0ZF9OzYDEN6t8e0xVtw5OwNiEUJNx237j+De49fJ9nG7zfCYwZ3xdTRfXH07A2s3HwIwT/DEB8fj/mThyQ5OTIqOvl5I6mJj1f8Skxa/xdjarlJV3xKWCq4U6sGWL9wPK7eeYKt+8/iR2Aw4uPjMXpQVxTMl747PC/efkHp4oUxsEcbXLzxME3FCADZUskL1uzBJweXJI8J/1UkX7zxEM9ef0LLRjVRv2ZFjOjfCSMHdIbtxKX/dFfnbxlx3STlwg07jBncDRZmpggLj0Cz+tVw7toDuRXEMuL1JUWSzGv+fSn+/hkfPWM1/AMSLzARJ0kYutWueV2s+78HtOWpkLCowoI1e3Diwm00b1Ad9WtWxMIpQzF6UFe07TsJPn6J36D/JhYnBHHq0l2cvHg7yWM+f3VL9vykjOjfEROH95J97eHti+qtbGFqYoQzu5YiNDwCK7cexjeP74iOiUHZkkUwa9xAWSy/pZa3hPjF+PzVFfNX707yWO/vCR8OFbDOhePbF8HZzRPzVu2Gt68/YmPj0KhOFQzr2wEiMZcQJ0orFhak0W4/fInenZqjQpliskmpiuTp44861crD0EBf7q5FkYJ509xG8M8wHD9/G8fP34ahgT7O7lmGCcN74sjZG7JPtGPj4mD37F2K7bRpWhsPn7+Tjdn/zdTECIHBie9Y/D+3X30VL1og1b6ECAoJTfRppY62NqxyJB6SklJuhPgRGILIqGgUzJd4mFWhJLYlJ6elhWwp4t9+fwLt8WvCbZumteHm4YPBE+Q/kZ40opfc1988fdCgVsKQndQKBTcPHyxatw+ndi3B4S3z0W3oLLnhKckVxb+/x6HhEWn6Hvv9CML+E1ew/8QVZDfPhuvH1mGsbbc/b7wzoPj29PFDraplE+U1qe9Vcs5ft8PE4b3QqnEt/AgMhqmJEc5fT3xnJ9XX938Cgn4iIjIqyZ/vogWtIZFI4P099efh/M3t1yTqgKCQFL8n9x6/Rvdhs5Ldb+/0DfZO37B+1wlUKV8CF/avRN+uLbFi8yEASV8TAUE/ERoWAS0tcZp/5gvlz5NoW8F8uWV3Ek9evIPnb/7Md/g9BKlWlbKwMDfF4IlLZAsKAEC+vDnT1G9S3Dx9UMqmUKqxN61fDfp6uhgwdhG8/vr+/P8wM0+fhJ/ZQvnzyN25sjA3VejdWCJ1xjkWpNG27DuNiMgorJk3FjkszBLtF0HYJ1V3Hr6Ejo42+nf7s2yhWCzGoB5t0nT+//+xioiMgquHD/R+DZcJCArBoxfv0adzC1jlME90/t/LVkok8bLx8b+1aVo7zUtBfvjijG+e3zGkd7tEb/wV6Zvnd9SoVEZuW5/OzeWGbgGp50aI+Ph4PHz2Di0a1pAbY18wX240rJ36WPHfdHS05YaQ6GgnfP0jMBjvvySs4vT7U/K/vzcVy9igcrkScm1dvvUYYrEYE5JYijcpXxzd0Hf0fBQrZI39G2ZDX09Xti8yMuEN+f9/H99/doKruzeG9+uYaDgI8Od6EovFiYbdBASFwNc/ELq6f/IfERmVaAiLUPcev4Gujg56dWom2yYSiZKcB5UcJ1dPfP7qinbN66Bdszr47heAp6/+vJlN6+v7f/Hx8bj/5A2aNagud7czh4UZOrasj+dvviAsPDLZ85Ny7/Fr/AwNx3+Duyb6GQD+fE/8fgTB7tk7uf+AhEUqtLTk/9R/cfwGiUQCPbnvVXSiZbDj4+Nx5fZjtGpcC8WTWFI1qWVxu7RpBCPDP/NI2jStjVxW2XHnVzHm7uUrF+OLtwmrkUl+3Xn5++dAR1sbA7q1SiE7Kbt44yHy5MyB3p2bJ9qnr6crm3MS//tO1V+/Hk2MDdH9/5YufvDsLWJiYzGop/zy2kN6t093jERZDe9YkEZzdffBqOmrsGXpZNid34qzV+7j01dXiCBC/rw50bFlfUgkEvikYT5FUm7cf47nbz5jxpj+yJcnJ766uKNlo1ppfrN178xmPHn5Ee+/OCE4JAzlShVFmya1sPfYn4mqM5Zuw7m9y3Hn5CYcPnMd37y+w9LCDJXLl0Buqxxo2n0MAOCW3QtMGNYTa+ePxYt3X1CyaEF0bFU/zWPTpVIppi3egv0bZuPm8fU4fv4WfH8EoWhBaxQvkh+9Rs799wQl4ciZG1gxexR2rpqOB0/foJRNITSoVQkBgfLLvKYlN0Ks2nYE9WpWxPl9K3Dg5BWIxWIM7NEGDs7fUCYNzzIAAB+/AIwa2Bn58uSEyzcvtGteF2VKFMGkBRtlqw/dsnuO1k1qYc+aGbj18CXy58mJvl1b4quLh9xY9McvP+DkxTuw7dUOhfLnwb1HryESi1C9Ymk8fvFetprV315/cMDAcYtxcNNc7Fg1DYPGL0ZcnARunj4I/hmGfl1aIjw8EhGRUXj94Ss8vH0xacFGHNo0D/dOb8bxC7fg4xeA3FbZUatKOYSFR6D/2IUwNjLAq+t7cenWY3z+6orwiEjUq14BFcvYYN6qP89xef/FCe1b1MPciYPx7pMjwiMicfPBC0Hfl2t3n+L1BwfMnTAYhfLlhpObJ5rVrw7zbAlzEtI6RPHCjYeYPKIXomNicfTsTbnz0vr6krJ88yHUq1EB5/Yux/4TVyCRSNCncwvo6upg0bq9KZ6blLDwSExfshUbFo3H9aPrcP66HQKCQpA3lyWa1K2CF2+/YOay7cmeX6daeSyaNgyXbj6CyzcvaGtpoXObhpDEx8utEvX+ixPqVi+PoX3aw9c/EO5evnjz8SsWr9+PWlXL4vKh1Th85jq+unjA3NQEZUoWQd3q5VG6vvydteCQUJzbuxzHL9yCpYUZbHu3g4u7t9xk+6S8fGePoJBQrF84DruPXIQUQJfWDRN9GPIvTl26m7DE88yRqF2lLF68/QKxlhhFC1qjbbM66DVyLt5/dsL9J28QHROL/etn49DpazAyMECvTs0QEBSCXFbZZe0FBv3EtgNnMWZwNxzYOAd3Hr5EmeJF0LBO5US/n4g0FQsL0njX7z1Do66jMaxfR9SrWRHd2zcBpAm3vW/ZvcDBU1f/eRzxb1KpFAPGLsT8yUPQqVUDSCHFjXvPsWDNbtw8viHV83cfvYRm9auhXs2K0NPRgaePH5ZvPoSt+/8se+no4oGWvcZjwvCe6NauMczNTPAjMASf7F3klpTcsOsEDPX10aFlPbRrVhcf7J3R778FmDG2f5pfz/0nb9B1yExMGNYTw/p2hFgsgpvHdxw5cz31k9Po8JnryJ83J3p2aIqGtSvh2etP6DF8Nk7sWCR3XFpyI8SHL87oM2oe5kwYhMkj+8D7uz9WbTmMYoXyoUhB69QbQMLE47Gz12LxtGHo1akZfgQGY8bSrXJvso6fvw3L7Obo26UF6teqBEcXD/w3czXaNK2DWlXk79yMn7seXxzd0LNDU8waPxChYeF499lJtmRmUh69eI/hU5Zj56rp2LhoAkZOX4W4OAnGzV6L6WP6Y9nMkdDR0ca4OevgccEXT15+RLv+kzFuSA8M7N4Ghob68A8IwpsPX2UrXEVGRmP/iSuoX7MiWjWq+es68MG0xVvkVkvbd/wKShcvjO7tm2BY3w7w8PYVXFjEx8ej338LsGDKEHRt2xjx0nhcu/MUa7YfxYX9KxGdyrMSfrtw3Q7TRveFoYEWLtywk9uX1teXlK/O7ug4cBqmj+mH/wZ1gVgsxusPDvhv5up/fl7Ob2ev3sd3/wCMHtgFI/p3hK6ODr77BeD5m8+y56Ek55ODK+4/fo2m9aoil1ULREZF4/NXV/QZNU+2eAAAzF+1Gytmj8bUUX1hYKCH4xdu483Hr/gRGIxWvSdiwrAeaNWoFvp3M0NQcCi+Ortj8fp9ifrbuPskStoUxH+DusDY0BAPn7/HjCVbU3zWD5AwBLL/mAWYM2Ewpo7qi+DQMJy5fBcPn7/H0a0LUjw3OVKpFIPGL8bQPu3RpU0jtGhUE5FR0XD3/I7dRy7C5VvCJHvnb14YOmkppozqi9njB8E/IBgHTl5BQFAI1s4fJ9fm8k2HEB0di75dWqB2lXJ4/dEBPUfMwcGNc5KIgEjziGBVOeNnoBIRZRF71s6ETZH8qNNumLJDob+0aFgDe9bORPsBU2TDayjz1KxSBqd3LU30vAwi0iycY0FElIy/5yUAQKH8udGoTmU8eflBSRERkPj78nuY2s/QcHz4kvxTsYmIKGNxKBQRUTKeXNqJExdu45vXd1jntkK/ri0RGxuHLftOKzs0jbZo6jDo6+vi1Tt76OrqoFXjmqhaoRSWbNgv96AzIiLKXCwsiIiSce/xa3RoWQ+W2c0RExOLV+/tsWzjQbi6p/0heaR4j168x7C+HdCkblXo6enCzcMHM5duS3ICOxERZR7OsSAiIiIiIsE4x4KIiIiIiARjYUFERERERIKxsCAiIiIiIsFYWBARERERkWAsLIiIiIiISDAWFkREREREJBgLCyIiIiIiEoyFBRERERERCcbCgoiIiIiIBGNhQUREREREgrGwICIiIiIiwVhYEBERERGRYCwsiIiIiIhIMBYWREREREQkGAsLIiIiIiISjIUFEREREREJxsKCiIiIiIgEY2Gh4rREIpgZGEBLJFJ2KGqHuROG+Us/5k4Y5i/9mLv0Y+6EYf7SLyvljoWFitMSi2FuaAgtMb9V/4q5E4b5Sz/mThjmL/2Yu/Rj7oRh/tIvK+VO/V8BEREREREpHQsLIiIiIiISjIUFEREREREJxsKCiIiIiIgEY2FBRERERESCaSs7ACIiIiL6o0DenOjYsi7EIhGkyg4mjUQA9HS0ER0bpzYxqwpl5k4EIF4qxdmrdvjm5Su4PRYWRERERCqiQN6c6N6+ETbvPYvwyChlh5NmIgA6WlqIlUhYWPwjZefOyEAfowZ2xPHzdwQXFywsMsL0AwprKgYAdoxXWHtERESkujq2rKt2RQWpt/DIKGzeexZDerfBul2nBLXFORZEREREKkIsErGooEwXHhkFsQKe/M3CgoiIiEhFcBgRKYsirj0WFkREREQkyMldSzBn4uAMa3/tgnHYs3ZmhrX/L55d2QXb3u2UHYZKYmFBRERERGpt4vCeuHl8vULb7NauMb7YHU20vWXvCTh8+rpC+8oqOHmbiIiISNUpcGGYNFnaL3P7UyOBQT+VHYLK4h0LIiIiIhJMS0uMRdOGwd7uGD7ePYzJI3vL9nVu3RBXD6/B10fH8fbWAWxeOgnZzbPJnW9TJD/2b5gDh4fH8fXRcZzdswwFrHMl2Vf50sXw4c4hjBrQGd3aNcbE4b1QunhheL+9CO+3F9GtXWMAgKmJEVbN+Q8f7hyCw8PjOLFjEUrZFJS1U8qmIE7uXIyvj47D4eFxXDuyFuVKFUXNKmWwbsE4ZDMxlrU5cXhPAImHQnm/vYheHZth95oZcH5yCg8vbEez+tXk4m1WvxoeXtgOl2encXLnYnRt2wjeby/C1MRIUM5VDe9YEBGRcFxmm0jjdW7TCMfO3UDrPhNRrnRRrJw9Gl7f/XHkzA3oaGthxZbDcHbzRA4LM8ybNBjrFo5D39HzAQC5rCxwZvdSPHn5EV2HzkRYWASqViwJbS2tRP3UrloOu9ZMx6J1+3D49HXo6+miRJECaFC7EroPmwUACA2LAADsWDkVUVEx6D16HkLDwtG3c0uc2L4YddoPQ/DPMGxaMgkf7V0wffFWSOIlKF28MOLi4vDyrT1mr9iBySN6o26H4QCA8IjkV+uaMKwHFq3bh4Vr92JQzzbYtGQiqrUcjOCfYciXJyd2rJqG3Ucu4siZGyhTojBmTxik6PSrBBYWRERERCSYj+8PzF25C1IAzt+8ULJoQQzt3R5HztzAsfO3ZMe5e/li1vIduHZkLQwN9BERGYUB3VsjNCwCI6atQFycBADg4u6dqI8WDWtgw6LxmDR/Iy7ceAgAiIqOQXhkJCQSCfwDgmXHVqtQChVK26Bcoz6IiY0DACxYuwfNG1ZH66a1cfj0deTNZYmt+8/Ayc0TAODq7iM7PzQsAlJI5dpMzvELt3Hu2gMAwNINB2Dbqx0qlLHBvcev0bdLCzi7eWHh2r3Ar9wUL1oA44Z0T3ty1YTaFRZisRgTh/dE59YNYZndDL7+gThx4TbW7Twud9zkEb3Rq1MzmJoY4eXbL5i2ZIvcxUJEREREivPmg4Pc16/e22NY3w4Qi8UoXbwQJg3vhVI2hZDN1AhiccJo/Ly5LeHo4oHSxQvj2ZtPsqIiKRXL2KBJ3aoYOnkZrt19mmo8pYoXhJGhPj7dPyK3XV9PFwV/DbHacegcVs35D11aN4Tds3e4ePMhvnl+/9eXji+ObrJ/R0ZF42doOHJYJAz1KlIwL959cpQ7/u3Hr//chzpQu8Ji1MDO6N+1FcbOWQsHZ3eUL1UUa+ePRWhYBHYfvZhwzIDOGNSrDcbNXgd3L19MGdkbR7YsQINOIxEdE6vkV0BERESkOfR0dXB0ywLce/Iao2asQmDQT+TNbYmjWxdAVyfhrWhUVEyq7Xzz/I6gkFD0aN8Et+xepFiEAICRgQF8fwShi+2MRPt+hoYDAFZvO4qzV+6jcb2qaFS7MiaO6IURU1ekqXD52//HIoVUVjxpErV7xVXKl8T1e09x2+4lPL39cPnWY9x/8hYVyhSTHWPbux3W7zyB6/ee4YujG8bMXouclhZo0bCGEiMnIiIiyroqlLGR+7pS2eJwdfdG0ULWsDA3xZL1+/H8zWc4uXkmmrj9xdEV1SuWhrZ24jkVvwUG/0TXITNRMF9ubF8xVe7YmNi4RG/kP9g7wyq7OeIkErh5+Mj9Fxj8Z2UnF3dv7Dx0Hj1HzMHV24/Ro30TAEBsbBy0FFAcOLt5oVyponLbypculszR6k3tCouX776gTvXyKJw/D4CE2fzVKpbEnUevAAD58+ZETksL2D17KzsnNCwCbz58ReXyJZQRMhEREVGWlyeXJeZOHIwiBfKiQ4t6GNSzDXYduQiv7/6IjonFoJ5tkD9vTjSrXw3jh8rPL9h77DJMjAyxddkUlCtVFIXy50bn1g1RpEBeueMCgkLQdehMFC1ojS1LJ0NLK+GtrKe3H/LnzYnSxQvBwswUujraePD0LV69t8fetTNRv2ZFWOexQpXyJTB1dF+UK1UU+nq6WDxtGGpWKYO8uS1RtUJJlC9dDI6uHgAAD29fGBsZok61crAwM4WBvl668nLw1DUULWSNmWP7o3D+PGjbrA66/1q1SirNWs9aV7uhUJv2nIKJkSEenNsKiSQeWlpiLNt0EGev3AcAWOUwB4BEE238A4Nhld08yTa1RCKFVKS/pX4z79/pJLEqAqXsd86Yu/Rh/tJPE3PH33uqQROvPUVRldyJfv33/zL77WdSMaR2/JnLd6Gvr4fLh1ZDEh+P3Ucu4vDpawCA8XPWYdp//TCoZ1t8tHfGwjV7sG/DHNnrDQ4JRbehMzFr/ECc2b0UEkk8Pjm44OXbz3I5EQH4ERCMbkNn4tSuJdi8ZBJGTV+FK7ceoVWjmji5cwnMTI0xfs46nLhwG31Hz8fU0X2xZv5YZDc3hf+PYDx9/REBAcGIl8TDPJsJNiycgBzZzRAY/BNXbz/G6q1HIALw6p09Dpy4gm3Lp8LC3BSrtx3Bmm1HZXH8f46S+loEwNPbF0MnLcPciYMxuFc7vH5vjw27TmDZrFGIjYmFSJRwpkgkApRYaIgA6CZz/cdIUh529qcNq8pqVSq1b14Xs8cPxMK1e+Hg7I7SxQtj/mRbzF+9Gycv3kGV8iVwYf9KVGjSD34/gmTnbVsxFZBKMXzqikRtmhkYwNzQUGExug5dq7C2AKAQl10kIhXH33tEitGjezOs3n4i0faYKXszNQ7dFQMztT9NM2pQF/Tu3AK1WtsqOxSZicO64djxG0nucw0ISFMbanfHYvb4gdi09xTOX7cDANg7fYN1bkv8N6grTl68IysmLLObyRUWlhZm+PTVJck2Q6OiEBGTEZ+3KY5faChi01gtUgIdLS1YmZgwd+nE/KUfc6cYzN+/47WXfqqSu+jYuCT7F2Xyk7D/dakbkUgEbbEYcfHxWW54jyL079YKbz85Iij4J6pWKIWh/Tpg37HLiJVIVCZ30bFx8AoOFtSG2hUW+vp6iI+XT7okPh4iccJtJHcvX/j6B6JOtfL45OAKADA2MkDFsjY4cPJKkm1KpFJIVPwXcKxEkubbUCSPuROG+Us/5k4Y5i/9mLv0U3bupMj8YU8K8esNsVQqVc/4M1jB/HkwxrYbzLKZwOu7P7YfOIeNe04m5EpFcidF2oc8JUftCoubD15gjG03eH33h4OzO8oUL4xhfTrg2PmbsmN2Hb6AsUO6w9XdO2G52VF94Osf+M9LhxERERERCTVv1S7MW7VL2WFkOLUrLGYt244po3pj6fQRyG6RDb7+gTh4+hrWbj8mO2bzvtMwNNDHitmjYWpihBdvPqP3yLl8hgURERERUQZRu8IiPCISc1fuwtyVKVd9K7cexsqthzMpKiIiIiIizaZ2z7EgIiIiIiLVw8KCiIiIiIgEY2FBRERERESCsbAgIiIiIiLBWFgQEREREWWwtQvGYc/amUrp+9SuJZg/OeOf8s3CgoiIiIiyHO+3F9GiYQ1lh6FR1G65WSIiIiJNE1czc58Grv1EK1P7o6yBdyyIiIiISBBdHW3MnWyLd3cOwuXZaZzbuxzlSxcDANSsUgbeby+iTrVyuHp4DZyfnMKF/StQpEBeuTaaN6iO60fXweXZaTy5tBMThvWAllbyb1V1tLWxeNowvLm5Hy7PTuP5ld0YPagLAODZlYTnne1ZOxPeby/Kvk5LP95vL6Jf15Y4tGkenJ+ewpNLO9G6Sa0UX79YLMbquf/h6eVdcH56CnbntmJwr7ZJHju8X0e8ubkfH+8dxpLpw6Gt/aeI09XRxpzxg/Dqxj44PTmJSwdXoWaVMrL95tlMsGXpJLy6sQ/OT07h9smN6NCinlz7Bvp6WL9wPBwfn8Cbm/sxrG+HFGNXJN6xICIiIiJBZo4fiJaNamLc7HXw8PHDyAGdcWTLfNRuO1R2zNTRfTF/zR4EBIVg+cyRWDN/DNoPmAoAqFaxFNYvHI/ZK3bg2etPKJgvN1bMHg0AWLP9WJJ9Du7VFs3qV8ewKcvh9d0feXNaIk+uHACAlr0n4OPdwxg3Zx3uPnoFSXz8P/UzZWQfLNmwH3NW7EDnNg2xddkUNOo6Gk6unknGIhaL4OMXgKGTlyEoOBRVKpTAytmj4fcjCBdvPJQdV6tKWfj6B6LrkJkomC83tq2Ygk8OLjh5/jYAYPH04bApnA8jpq6Ar38gWjaqicOb56Nx19FwdfeBnp4O3n9xxuZ9pxEaFoEmdatiw6IJcPP0wduPjgCA2RMGoWblMhg4bhF+BIZg+n/9ULZEEXxycPn3b+w/4h0LIiIiIko3A3099OvaEkvW78fdR6/g6OKByQs2Iio6Bj07NpUdt3zTQTx99RGOLh7YtPcUqlYoBT1dHQDAxGE9sWnvKZy8eAfuXr548PQtVmw+hD6dWyTbb95clnBx98bzN5/h5eOP528/49y1BwCAwKCfAICfoeHwDwiWfZ3Wfi7efIgjZ2/Axd0bK7ccxrvPjhjUM+k7EAAQFyfBqq1H8P6zEzy8fXH2yn0cP38LbZvWkTsuJDQMM5dth5ObJ27ZvcAtu5eoU608ACBPLkt0b9cEQycvx/M3n/HN8zu2HTiLF28+o3v7JgCA736B2HbgLD45uMLdyxd7jl3C3cev0a5pXQCAoYE+enZoigVr9+Dh8/ewd/qGsbPXQlsrc4a28Y4FEREREaVbwXy5oaujg1dvv8i2xcVJ8PbjVxQrlA9vPyV8kv7Z0U22388/CACQw8IMXt/9UcqmEKpUKImxtt1kx4jFYhjo68FAXw9zJw5G59YNZPuK1eqGExdu4+i2BbA7vw33Hr3GLbsXuP/kTYqxptZPZFQ0AODVe3u58169d0Dp4oUAAIc2zUP1SqUAAJ4+/mjYeRQAYED3VujRviny5rKEvr4udHS08cnBVa4dB2d3xP+6ewIAfj8CUbJoAQBAyWIFoK2thYfnt8mdo6ujg6CQUFmsYwZ3RdtmdZDLKjt0dbShq6Mji7tgvlzQ09XBmw9fZecH/wyD87ek77QoGgsLIiIiIspwcXF/JqBLIQUAiMQiAIChoT5WbzuCK7efJDovKjoGK7ccxrYDZ+W2f7B3Ro3WtmhUuzLq1qiAbSumwO7pOwydvCzZGFLrJy0mLdgAfT09AEBsXBwAoH3zupg9fhAWrNmDV+/sERYRiRH9O6FSWRu5c//OAQBIpVKIxAkDiIwM9BEXJ0GLnuNlQ7d+C4+IBACM7N8Jtr3aYc7KnbB3ckNEZDTmTx4CXR3VeEuvGlEQERERkVpy8/BBdEwsKlcoCTev7wAAbW0tlC9dDLsOX0hTGx/tnVGkQF64efgkuT8gKAQBQSGJtoeFR+LCjYe4cOMhLt18hKNbF8DM1BjBP8MQExsLsVh+1H9q/fxWqVwJnLp098/XZYvj4685Ct/9AhMdX7VCSbx8Z4/9J67IthW0zpViH//vo70LtLW1kN0iG56/+ZzkMVUrlMT1e09x5so9AIBIJELhAnng6OIBAHDz+I6Y2FhULGsDr+/+AIBsJkYoXCAvnrz6+E/xpAcLCyIiIiJKt8ioaBw8eQUzxvZHQFAIPL/7Y+SAzjDQ18PRszdQ6tcQopSs2X4MBzbMgdd3f1y69Rjx8fEobVMIxYsWwIrNh5I8Z2if9vD7EYSP9i6Ij49H26Z14OsfiJDQcACAh7cf6lQvjxdvPyMmJhYhoeFp7qdtk9p4/8kRz998RqfWDVCxTDFMnL8h2fhd3X3QpU0j1K9ZER5evujcpiHKly4GD2/fNOfRxd0bpy/fxYZFEzB/9W58tHdBdgtT1KlWHl8c3XDb7iVc3L3RpkltVClfAsE/wzCsbwdYWpjJCouIyCgcPXsTs8cPRFBwKH4EBmPa6L5yw68yEgsLIiIiIhJkyfr90NLSwoZFE2BkZID3n53Qa+Rc2Zv81Nx/8gb9xizAhGE9MGpAF8TGxcHJzRNHzt5I9pywiEiMHNAJhfLngUQSj3efHNF39HxIpQnDrBas3o25k2zRu2MzfPcPQPVWtmnuZ9W2I2jfoh6WzBgBvx9BGDl9lezNe1IOnrqKMiUKY9uKKZBKgXPXHmD/iStoVKdyml7/b+Pnrse4Id0xd+Jg5LKyQGDQT7z+4IBbD14AANbvPI4C1rlwZMt8REZF49Dp67h27ylMjY1kbSxcuxdGhgbYv2E2wsIjsf3gWZiYGCXXpUKJYFVZmik9aZLpBxTaXKEd4+EVHIwYSeY+HEfd6WppIa+ZGXOXTsxf+mlk7vh7TyVo5LWnIKqSu/FDumLtzpNK6z+9RAB0tLQQK5FA3d9Yer+9iEHjF+Pa3aeZ0p+q5E4R1x6XmyUiIiIiIsE4FIpUiwI/9YwBgB3jFdYeERERESWPhQURERER0S95KiT/IDxKGYdCERERERGRYCwsiIiIiIhIMBYWRERERCpCpOwASGMp4tpjYUFERESkIuKlUhgZ6Cs7DNIwRgb6iJcKX+yWhQURERGRijh71Q6jBnZkcUGZxshAH6MGdsTZq3aC2+KqUEREREQq4puXL46fvwPbXq2hJRarzcPmRAD0dLQRHRunNjGrCmXmToSEu2THz9/BNy9fwe2xsCAiIiJSId+8fLF+92llh/FPVOXJ5eooK+WOQ6GIiIiIiEgwFhZERERERCQYh0IREREp0/QDCmsqBgB2jFdYe0RE/0It71jksrLAxsUT8PHeYTg/PYXbJzeiXKmicsdMHtEbb27uh/PTUzi+bSEK5c+tpGiJiIiIiLK+TCks9HR1oKujmJsj2UyMcH7fCsTFSdBn9Dw06DQKC9bsQcjPMNkxowZ0xqBebTBt8Ra06TsJEZFROLJlAfR0dRQSAxERERERycuQoVA1q5RB8wY1ULVCSdgUzgd9PV0AQGRUNBxdPfHy3Rdcu/sUT15+/Oe2Rw3sAu/vPzB+7nrZNg9v+eWxbHu3w/qdJ3D93jMAwJjZa/Hu9kG0aFgD568LX6OXiIiIiIjkKayw0NbWQt/OLTC0bwfky2OF4JAwfLB3xunL9xDyMwwikQjZTI2RP29OdG7VEIN7toWnjz+2HziLg6evIS4ubctrNatfDfeevMH2lVNRs3IZfPcLwL4TV3DkzA0AQP68OZHT0gJ2z97KzgkNi8CbD19RuXyJJAsLLZEIWmLF3byJUVhLf+hoaWVAq6qHuVMdv/PG/P07Tcwdf3bTj7lTDZr4c6tIzF/6qUPu0roMrsIKi8cXdkBHRxsnL97BxRsP8cHeOcXjy5YsgrZN6+C/wV0xvH9HVG9lm6Z+8lvnQr+uLbHj0Dls3HUS5csUw8IpQxEbG4eTF+/AKoc5AMA/IFjuPP/AYFhlN0+yTRN9fZgbGqap/7RwVVhLf1iZmGRAq6qHuVM9zF/6aVLu+LObfsydamHuhGH+0k+Vc+caEJCm4xRWWGzYfRInLtxCTGxcmo7/8MUZH744Y+WWw+jevkma+xGLRXj/2QnLNh4EAHx0cEGJIgXQt0tLnLx4J12xh0ZFISImIz4zUhy/0FDEqvlDU5SFuUsfHS0tWJmYMH/pwNwpBvOXfszdv+PPrTDMX/plpdwprLA4dPpaus6LjYv7p3P9/IPw1dlDbpujqwdaNamVsP9HEADAMruZ7N8AYGlhhk9fXZJsUyKVQqLi38hYiUTtn8aoLMydMMxf+jF3wjB/6cfcpR9zJwzzl35ZIXeZvtysjrY2DPT10n3+i3dfUKRgXrlthQvkhZePHwDA3csXvv6BqFOtvGy/sZEBKpa1wat39unul4iIiIiIkpdhhUX75nUxb5L8vIkJw3rA8ckJ2Nsdw+41M2BooP/P7e44dB6VyhbHf4O7omC+3OjYsj76dG6Ovccvy47ZdfgCxg7pjmb1q6FE0QLYsGgCfP0Dce3uU8Gvi4iIiIiIEsuwJ28P69cRH/+awF2lfAlMGNYTt+1ewtHVAwN7tMFY225YuvHfnjj67pMjBk9Ygulj+mH80B7w8PLFnJU7cfbKfdkxm/edhqGBPlbMHg1TEyO8ePMZvUfORXRMrMJeHxERERER/ZFhhUUB61w4eeG27OuOLevD70cQBk1YDIkkHmKRGK2a1PrnwgIAbtm9wC27Fykes3LrYazcevif2yYiIiIion+XYUOh9HR15O4Q1KtZEXcfvYJEEg8A+OrijjxWOTKqeyIiIiIiykQZVli4e/mibvWECdTlShVFoXy5cffxa9n+HNnNEB4ZmVHdExERERFRJsqwoVCHTl3DgilDUKxwPuTOmQM+vgG49eDP8KWqFUrBwdk9o7onIiIiIqJMlGGFxZ5jlxAVE4PGdargwxdnbN57GlHRCQ+hMzM1hlV2Mxw8lb5nXxARERERkWrJsMICAI6cuYEjZ24k2h78Mwwte0/IyK6JiIiIiCgTZfoD8oiIiIiIKOtRWGFxZMt8VK9U+p/Pq1WlLI5sma+oMIiIiIiISAkUNhTKzfM7jm1bCHfP77hwww52z97ho70LIiKj5I4zMjRAuVJFULd6BbRtWht5c1vh2LmbigqDiIiIiIiUQGGFxYwlW7F13xnY9m6L/t1aYdyQ7pBKgeCfoQj5GQaIRDAzMUY2U2OIREBwSBjOXL2HXYcvwsPbV1FhEBERERGREih08raHty/mrtyFBWv2oHrF0qhcvgSKFrSGuZkJACAoOBRObp549c4ez99+RlycRJHdExERERGRkmTIqlASSTwev/yAxy8/ZETzRERERESkYrgqFBERERERCcbCgoiIiIiIBGNhQUREREREgrGwICIiIiIiwVhYEBERERGRYCwsiIiIiIhIsAxZbvY3sViMtk1ro1bVcshhkQ0rtxyGvdM3mBgbok618njx9gt+BAZnZAhERERERJQJMqywMDUxwuHN81CxjA3CI6JgaKCHPUcvAQDCI6KwcOpQnLp0B8s2HsyoEIiIiIiIKJNk2FCoGWP6o3iR/Og1ci5qthkCkUgk2xcfH4/Ltx6hcZ0qGdU9ERERERFlogwrLFo0rIE9xy7hwdO3kEqlifa7fPOGdR6rjOqeiIiIiIgyUYYVFibGhnD38k12v7a2FrS1tDKqeyIiIiIiykQZVlh88/yOsiWKJLu/fs2K+OrikVHdExERERFRJsqwwuLI2Rvo0aEp2jWrI5tfIZVKoaujjamj+6JhrUo4dOpaRnVPRERERESZKMNWhdp1+AKKF8mPLcsmIyQ0HACweekkmJuZQFtLCwdPXcPRczczqnsiIiIiIspEGfoci8kLNuHkhTto3bQWCuXPA7FIjG+ePrhw4yGevf6UkV0TEREREVEmytDCAgCev/2M528/Z3Q3RERERESkRBk2x4KIiIiIiDRHht6x6NSqAXp0aIIC1rmQzcRY7iF5QMJk7hJ1e6S7/dEDu2DG2P7Yefg85q7cBQDQ09XB3ImD0a55Xejp6uDe4zeYvmQrfgQGC3kpRERERESUggwrLGaO7Y/h/Triu18g3n12RGhYhELbL1+6GPp0aYFPDq5y2+dNskWTulUxbPJy/AwLx+Jpw7F7zXS0HzBVof0TEREREdEfGVZY9OrUHLcevMCgCUuSfPK2EIYG+ti0ZCImL9iIsUO6y7abGBuiZ8emGDV9FR69eA8AmDB3PR6c24pKZYvj9QcHhcZBREREREQJMnQo1O2HrxReVADAkhnDcdvuJeyevZMrLMqVLApdHR3YPXsn2+bk5glPbz9ULl8i2cJCSySCllhx001iFNbSHzoa8pRy5k51/M4b8/fvNDF3/NlNP+ZONWjiz60iMX/ppw65i5FI0nRchhUWtx68QLWKpXDotGIfgte+eV2ULVEErXpPSLTPKoc5omNi8fPXczN+8w8MhlV2s2TbNNHXh7mhocJidE39kH9mZWKSAa2qHuZO9TB/6adJuePPbvoxd6qFuROG+Us/Vc6da0BAmo7LsMJi1vLt2L9+NhZPG4Zj527By9cf8ZL4RMcF/wxLc5t5cubAgilD0GP4HETHxCos1tCoKETEZMRnRorjFxqK2DRWiySPuUsfHS0tWJmYMH/pwNwpBvOXfszdv+PPrTDMX/plpdxlWGERERmFl+/sMaJ/R/Tr2jLZ4/JV7pDmNsuVKgrL7Oa4fnSdbJu2thZqVCqNgd3boNfIOdDT1YGpiZHcXQtLCzP4BQQn265EKoVExb+RsRJJmm9DkTzmThjmL/2YO2GYv/Rj7tKPuROG+Uu/rJC7DCssFk8bjt6dmuH1Bwe8/vAVoWHhqZ+UCrtn79Cw8yi5bWsXjIOTqyc27z0Fb98fiImNRZ1q5XHl9mMAQJECeWGdxwqv3tkL7p+IiIiIiJKWYYVFu+Z1ceryPYyfs05hbYZHRMLB2V1uW0RkFIJCfsq2Hz17E/MmDkZwSChCwyOweNowvHz3hStCERERERFloAwrLOLi4vD6febfJZi3ahekUil2rp7+6wF5rzF9ydZMj4OIiIiISJNkWGFx/podmtavhoOnFLsq1P/rYjtD7uvomFjMWLoNM5Zuy9B+iYiIiIjojwwrLC7csMOiqcNwYOOchFWhvie9KtQHe+eMCoGIiIiIiDJJhhUWZ/csAwCULl4IDWtVSrRfJBJBKpX+06pQRERERESkmjKssBg/d31GNU1ERERERComwwqLkxfvZFTTRERERESkYsTKDoCIiIiIiNSfwu5YrJk3BlKpFJMXbkZ8fDzWzBuT6jlSqRQT529UVAhERERERKQkCissalcrh/h4KcRiEeLjE76WSlM+R5raAUREREREpBYUVlhUb2Wb4tdERERERJR1Zdgci7y5LKGvp5vsfn09XeTNZZlR3RMRERERUSbKsMLi6eWdaNmoZrL7m9WvhqeXd2ZU90RERERElIkyrLAQiUQp7tfW1kZ8POdYEBERERFlBQp9joWxkQGymRjLvjbPZpLkcCdTEyO0b1EPfj+CFNk9EREREREpiUILi6F92mP80B4AElZ8mj/ZFvMnJz2JWyQSYfnmQ4rsnoiIiIiIlEShhcX9J28QHhEFkUiEWeMG4Ny1B/jwxVnuGKlUiojIaLz/4oT3n50U2T0RERERESmJQguLV+8d8Oq9AwDA0EAPl289hoOzuyK7ICIiIiIiFaTQwuJva7Yfy6imiYiIiIhIxWTYqlBERERERKQ5WFgQEREREZFgLCyIiIiIiEgwFhZERERERCQYCwsiIiIiIhKMhQUREREREQnGwoKIiIiIiARjYUFERERERIKxsCAiIiIiIsFYWBARERERkWAsLIiIiIiISDAWFkREREREJJi2sgP4V6MHdUGrxrVQtGBeREXH4OU7eyxetw/O37xkx+jp6mDuxMFo17wu9HR1cO/xG0xfshU/AoOVFzgRERERURamdncsalYug33HL6NNv8noMXw2tLW1cHTrAhjo68mOmTfJFk3rVcOwycvRafB05LS0wO4105UYNRERERFR1qZ2dyx6j5on9/W4Oevw8e5hlCtVFM9ef4KJsSF6dmyKUdNX4dGL9wCACXPX48G5rahUtjhef3BQQtRERERERFmb2t2x+H+mxkYAgOCQUABAuZJFoaujA7tn72THOLl5wtPbD5XLl1BKjEREREREWZ3a3bH4m0gkwvzJQ/D8zWc4OLsDAKxymCM6JhY/Q8PljvUPDIZVdrMk29ESiaAlVlyNFaOwlv7Q0dLKgFZVD3OnOn7njfn7d5qYO/7sph9zpxo08edWkZi/9FOH3MVIJGk6Tq0LiyXTh6NE0fzoMGCqoHZM9PVh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3NX76NOlOSqXKy7bJpVKAQC9OjVD26Z1cOrSXWEREhERERGRyhO0KtT6nSdQqWxxnNm9DI6uHpBKpZg/2RZmpibInTM7bj98hR2HzisqViIiIiIiUlGCCovYuDj0GjkXnVo1QJumtaGlpQVdHR18dnTD8s0HebeCiIiIiEhDKOQBeWeu3MOZK/cU0RQREREREakhwYVFtQql0KNDE+S3zoVsJsb461EWAACpFGjafYzQboiIiIiISIUJKiyG9mmP2eMHIjomFs5uXgj+GaqouIiIiIiISI0IKixG9O+EF2+/oP/YhQgNi1BUTEREREREpGYELTdroK+HM1fus6ggIiIiItJwggqLxy8/oGSxAoqKhYiIiIiI1JSgwmLWsu2oU608hvfrCDNTY0XFREREREREakbQHAtv3x84ePoa5owfhJlj+yM6JhYSSbzcMVKpFCXq9hAUJBERERERqTZBhcXkEb0xxrYrvvsF4t1nR861ICIiIiLSUIIKi75dW+C23UsMHL8YUqlUUTEREREREZGaETTHQkdHG7fsXrKoICIiIiLScIIKi1sPXqB6pVKKikWhBnRvhWdXdsHl2WlcOrgKFcoUU3ZIRERERERZlqDCYs32o7ApnB9LZoxA2ZJFYGFuCjNT40T/ZbZ2zepg7kRbrNl+FM17jsPnr644smUBsptny/RYiIiIiIg0gaA5FnbntgEAShcvhL6dmyd7XL7KHYR088+G9u2AI2eu4/j52wCAqYu2oHHdqujZoSk27T2VqbEQEREREWkCQYXF2h3HVG5+hY62NsqVLIpNe/4UEFKpFHbP3qJyueJKjIyIiIiIKOsSVFis3nZUUXEojIW5KbS1teAfECS3/UdAMIoWtE7yHC2RCFpiQaPC5MQorKWMoaulpewQksXcCcP8pR9zJ4wq54+5E4b5Sz/mThhVzp+m5S5GIknTcSJYVVatWw4C5bS0wJub+9G23yS8eu8g2z5r3ADUqFwGbfpOUmJ0RERERERZk+I+plcRgUE/ERcngWV2c7ntObKbwf9HUDJnERERERGREFmusIiNi8P7L06oU62cbJtIJEKdauXl7mAQEREREZHiCJpjoap2HDyHdQvH491nJ7z5+BVDereHoYE+jp2/pezQiIiIiIiypCxZWFy48RDZzbNh8ojesMxhjk8OLug9ci5+BAYrOzQiIiIi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TCGTFXFAIiPmvGNhQURERKRCdEwc7GvVQERklNLxenbWiI17K1BUuk0mk+HCofV5fp99YTLlJOa8Y2FBREREpILv8XNYMGMk4t8l4NK1WwCA5o0cMH/6CPxx3F/g6HST6wg3oUMQPTHnHbtCEREREalgZGiINQsnw6lTS6SmpQEA5DI5Dhw+gxnuvyElNVXgCEmKxJx3LCyIiIiI8mBjVRX2ta2RmJiMO6GP8PTZS6FDIj0gxrzjVCgiIiKiPDyJjIJMJsOjiGdIS0sXOhzSE2LMO7abJSIiIlLB1MQYHnPGI+zSAZz19kS1Dx153GeMxLghrgJHR1Il5rxjYUFERESkwqwJg2BvZw3X4T8qtU/1v3wdPbu0EjAykjIx5x2nQhERERGp0LVdM4yesQTXgkOUWqSGhIWjukUVASMjKRNz3vGNBREREZEK5cuWxquY1zmOFzc15l4MVGjEnHcsLIiIiIhUuH77Pjq2bpL1OfOe7ptenXH1xl2BoiKpE3PecSoUERERkQqL1+zATs85qGVjCQMDAwwf0AN2NlZo3KAOvho2S+jwSKLEnHfcx4KIiIgoF9UtKmPcUFfY21nDzNQEwXfD4LnVG3dDHwsdGkmYWPOOhQURERHRJ+resQWOnL4odBikZ3Q977jGgoiIiOgjBgZy1La1go1VVaXjXdo1xam9q7H2l6kCRUZSJva84xoLIiIiomxq21ph+5rZqFqpAgDghN9lzFy4DhuWzEDtmlbY7XMSg8bPEzhKkhop5B2nQhERERFls33NbBgbGeH3XX/ApVsbuHRtg7BHT7HH9xS27T2CxKTk/E9C9ImkkHd8Y0FERESUTcN6tdB/zGzcCnmIy0G34NK1DVZv3g/vI2eFDo0kTAp5xzUWRERERNmUK1MKz6NiAABv49/jfUIirgXr9v4BJH5SyDu+sSAiIiLKRqFQoISZKZKSkyGTyaBQACbGxihhZqr0u/h3CQJFSFIkhbzjGgsiIiKibCKuHYJC8d/tUcZNXs7Plo1cBIiOpEoKecc3FkRERETZuI5wEzoE0kNSyDu+sSAiIiIiIo1x8TYREREREWmMhQUREREREWmMhQUREREREWmMhQUREREREWmMhQUREREREWmMhQUREREREWmMhQUREREREWmMhQUREREREWmMhQUREREREWmMhQUREREREWmMhQUREREREWmMhQUREREREWmMhQUREREREWns/wGhiIYr0GgfWwAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 800x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Results\n",
    "# ==============================================================================\n",
    "summarize_results(\n",
    "    results   = results_grid_search,\n",
    "    metric    = metric,\n",
    "    plot      = True,\n",
    "    fig_size  = (8, 6),\n",
    "    title     = 'Grid search using backtesting vs one-step-ahead',\n",
    "    save_plot = \"../img/grid_search_benchmarck.png\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Bayesian search"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Table to store results\n",
    "# ==============================================================================\n",
    "results_bayesian_search = []\n",
    "metric = 'mean_absolute_error'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭─────────────────────────── OneStepAheadValidationWarning ────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> One-step-ahead predictions are used for faster model comparison, but they may not    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> fully represent multi-step prediction performance. It is recommended to backtest the <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> final model for a more accurate multi-step performance estimate.                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : OneStepAheadValidationWarning                                             <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> st/model_selection/_utils.py:675                                                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m──────────────────────────\u001b[0m\u001b[38;5;214m OneStepAheadValidationWarning \u001b[0m\u001b[38;5;214m───────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m One-step-ahead predictions are used for faster model comparison, but they may not    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m fully represent multi-step prediction performance. It is recommended to backtest the \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m final model for a more accurate multi-step performance estimate.                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : OneStepAheadValidationWarning                                             \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m st/model_selection/_utils.py:675                                                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------\n",
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 87.15898752212524\n",
      "Execution time one step ahead: 27.95840358734131\n",
      "Same lags   : True\n",
      "Same params : True\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [  1   2   3  23  24  25 167 168 169]\n",
      "    params : {'n_estimators': 1200, 'max_depth': 10, 'learning_rate': 0.017833474222028703, 'gamma': 0.2285821738161964, 'reg_alpha': 0.2379772800670556, 'reg_lambda': 0.9887301767538853}\n",
      "    mean_absolute_error: 55.80577702511616\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [  1   2   3  23  24  25 167 168 169]\n",
      "    params : {'n_estimators': 1200, 'max_depth': 10, 'learning_rate': 0.017833474222028703, 'gamma': 0.2285821738161964, 'reg_alpha': 0.2379772800670556, 'reg_lambda': 0.9887301767538853}\n",
      "    mean_absolute_error: 55.80577702511616\n"
     ]
    }
   ],
   "source": [
    "# Dataset bike_sharing_extended_features - ForecasterRecursive\n",
    "# ==============================================================================\n",
    "end_train = '2012-03-31 23:59:00'\n",
    "end_validation = '2012-08-31 23:59:00'\n",
    "exog_features = [\n",
    "    'month_sin', 'month_cos', 'week_of_year_sin', 'week_of_year_cos', 'week_day_sin',\n",
    "    'week_day_cos', 'hour_day_sin', 'hour_day_cos', 'sunrise_hour_sin', 'sunrise_hour_cos',\n",
    "    'sunset_hour_sin', 'sunset_hour_cos', 'holiday_previous_day', 'holiday_next_day',\n",
    "    'temp_roll_mean_1_day', 'temp_roll_mean_7_day', 'temp_roll_max_1_day',\n",
    "    'temp_roll_min_1_day', 'temp_roll_max_7_day', 'temp_roll_min_7_day',\n",
    "    'temp', 'holiday'\n",
    "]\n",
    "\n",
    "forecaster = ForecasterRecursive(\n",
    "                 estimator = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                 lags      = 10\n",
    "             )\n",
    "\n",
    "lags_grid = [48, 72, (1, 2, 3, 23, 24, 25, 167, 168, 169)]\n",
    "\n",
    "\n",
    "def search_space(trial):\n",
    "    search_space  = {\n",
    "        'n_estimators' : trial.suggest_int('n_estimators', 400, 1200, step=100),\n",
    "        'max_depth'    : trial.suggest_int('max_depth', 3, 10, step=1),\n",
    "        'learning_rate': trial.suggest_float('learning_rate', 0.01, 1),\n",
    "        'gamma'        : trial.suggest_float('gamma', 0, 1),\n",
    "        'reg_alpha'    : trial.suggest_float('reg_alpha', 0, 1),\n",
    "        'reg_lambda'   : trial.suggest_float('reg_lambda', 0, 1),\n",
    "        'lags'         : trial.suggest_categorical('lags', lags_grid)\n",
    "    }\n",
    "\n",
    "    return search_space\n",
    "\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark(\n",
    "    data                    = data_bike,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'bayesian_search',\n",
    "    search_space            = search_space,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    target                  = 'users',\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 24,\n",
    "    metric                  = metric\n",
    ")\n",
    "\n",
    "results_bayesian_search.append([\n",
    "    'bike_sharing',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭─────────────────────────── OneStepAheadValidationWarning ────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> One-step-ahead predictions are used for faster model comparison, but they may not    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> fully represent multi-step prediction performance. It is recommended to backtest the <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> final model for a more accurate multi-step performance estimate.                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : OneStepAheadValidationWarning                                             <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> st/model_selection/_utils.py:675                                                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m──────────────────────────\u001b[0m\u001b[38;5;214m OneStepAheadValidationWarning \u001b[0m\u001b[38;5;214m───────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m One-step-ahead predictions are used for faster model comparison, but they may not    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m fully represent multi-step prediction performance. It is recommended to backtest the \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m final model for a more accurate multi-step performance estimate.                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : OneStepAheadValidationWarning                                             \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m st/model_selection/_utils.py:675                                                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------\n",
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 17.606075286865234\n",
      "Execution time one step ahead: 0.9842092990875244\n",
      "Same lags   : False\n",
      "Same params : False\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48\n",
      " 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72]\n",
      "    params : {'alpha': 121.0898788312409}\n",
      "    mean_absolute_error: 79.1498337214025\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [  1   2   3  23  24  25 167 168 169]\n",
      "    params : {'alpha': 15.094374246471325}\n",
      "    mean_absolute_error: 111.96208734026862\n"
     ]
    }
   ],
   "source": [
    "# Dataset bike_sharing_extended_features - ForecasterDirect\n",
    "# ==============================================================================\n",
    "forecaster = ForecasterDirect(\n",
    "                 estimator     = Ridge(random_state=123),\n",
    "                 transformer_y = StandardScaler(),\n",
    "                 steps         = 24,\n",
    "                 lags          = 10\n",
    "             )\n",
    "\n",
    "lags_grid = [48, 72, (1, 2, 3, 23, 24, 25, 167, 168, 169)]\n",
    "\n",
    "\n",
    "def search_space(trial):\n",
    "    search_space  = {\n",
    "        'alpha': trial.suggest_float('alpha', 0.001, 1000, log=True),\n",
    "        'lags' : trial.suggest_categorical('lags', lags_grid)\n",
    "    }\n",
    "\n",
    "    return search_space\n",
    "\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark(\n",
    "    data                    = data_bike,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'bayesian_search',\n",
    "    search_space            = search_space,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    target                  = 'users',\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 24,\n",
    "    metric                  = metric\n",
    ")\n",
    "\n",
    "results_bayesian_search.append([\n",
    "    'bike_sharing',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭─────────────────────────── OneStepAheadValidationWarning ────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> One-step-ahead predictions are used for faster model comparison, but they may not    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> fully represent multi-step prediction performance. It is recommended to backtest the <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> final model for a more accurate multi-step performance estimate.                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : OneStepAheadValidationWarning                                             <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> st/model_selection/_utils.py:675                                                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m──────────────────────────\u001b[0m\u001b[38;5;214m OneStepAheadValidationWarning \u001b[0m\u001b[38;5;214m───────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m One-step-ahead predictions are used for faster model comparison, but they may not    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m fully represent multi-step prediction performance. It is recommended to backtest the \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m final model for a more accurate multi-step performance estimate.                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : OneStepAheadValidationWarning                                             \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m st/model_selection/_utils.py:675                                                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------\n",
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 1.0920460224151611\n",
      "Execution time one step ahead: 0.26500821113586426\n",
      "Same lags   : False\n",
      "Same params : False\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21]\n",
      "    params : {'alpha': 0.07474245141964296}\n",
      "    mean_absolute_error: 136.76802274106467\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14]\n",
      "    params : {'alpha': 0.03182234592129467}\n",
      "    mean_absolute_error: 173.5282998809151\n"
     ]
    }
   ],
   "source": [
    "# Dataset website_visits - ForecasterRecursive\n",
    "# ==============================================================================\n",
    "end_train = '2021-03-30 23:59:00'\n",
    "end_validation = '2021-06-30 23:59:00'\n",
    "exog_features = [col for col in data_website.columns if col.startswith(('month_', 'week_day_', 'month_day_'))]\n",
    "\n",
    "forecaster = ForecasterRecursive(\n",
    "                 estimator     = Ridge(random_state=123),\n",
    "                 transformer_y = StandardScaler(),\n",
    "                 lags          = 10\n",
    "             )\n",
    "\n",
    "lags_grid = [7, 14, 21, [7, 14, 21]]\n",
    "\n",
    "\n",
    "def search_space(trial):\n",
    "    search_space  = {\n",
    "        'alpha': trial.suggest_float('alpha', 0.001, 1000, log=True),\n",
    "        'lags' : trial.suggest_categorical('lags', lags_grid)\n",
    "    } \n",
    "    \n",
    "    return search_space\n",
    "\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark(\n",
    "    data                    = data_website,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'bayesian_search',\n",
    "    search_space            = search_space,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    target                  = 'users',\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 7,\n",
    "    metric                  = metric\n",
    ")\n",
    "\n",
    "results_bayesian_search.append([\n",
    "    'website',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭─────────────────────────── OneStepAheadValidationWarning ────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> One-step-ahead predictions are used for faster model comparison, but they may not    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> fully represent multi-step prediction performance. It is recommended to backtest the <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> final model for a more accurate multi-step performance estimate.                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : OneStepAheadValidationWarning                                             <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> st/model_selection/_utils.py:675                                                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m──────────────────────────\u001b[0m\u001b[38;5;214m OneStepAheadValidationWarning \u001b[0m\u001b[38;5;214m───────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m One-step-ahead predictions are used for faster model comparison, but they may not    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m fully represent multi-step prediction performance. It is recommended to backtest the \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m final model for a more accurate multi-step performance estimate.                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : OneStepAheadValidationWarning                                             \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m st/model_selection/_utils.py:675                                                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------\n",
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 1.5587255954742432\n",
      "Execution time one step ahead: 0.3095226287841797\n",
      "Same lags   : False\n",
      "Same params : False\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21]\n",
      "    params : {'alpha': 0.07474245141964296}\n",
      "    mean_absolute_error: 139.40123604696382\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14]\n",
      "    params : {'alpha': 0.03182234592129467}\n",
      "    mean_absolute_error: 153.6723680506666\n"
     ]
    }
   ],
   "source": [
    "# Dataset website_visits - ForecasterDirect\n",
    "# ==============================================================================\n",
    "forecaster = ForecasterDirect(\n",
    "                 estimator     = Ridge(random_state=123),\n",
    "                 transformer_y = StandardScaler(),\n",
    "                 lags          = 10,\n",
    "                 steps         = 7\n",
    "             )\n",
    "\n",
    "lags_grid = [7, 14, 21, [7, 14, 21]]\n",
    "\n",
    "\n",
    "def search_space(trial):\n",
    "    search_space  = {\n",
    "        'alpha': trial.suggest_float('alpha', 0.001, 1000, log=True),\n",
    "        'lags' : trial.suggest_categorical('lags', lags_grid)\n",
    "    } \n",
    "    \n",
    "    return search_space\n",
    "\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark(\n",
    "    data                    = data_website,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'bayesian_search',\n",
    "    search_space            = search_space,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    target                  = 'users',\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 7,\n",
    "    metric                  = metric\n",
    ")\n",
    "\n",
    "results_bayesian_search.append([\n",
    "    'website',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭─────────────────────────── OneStepAheadValidationWarning ────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> One-step-ahead predictions are used for faster model comparison, but they may not    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> fully represent multi-step prediction performance. It is recommended to backtest the <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> final model for a more accurate multi-step performance estimate.                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : OneStepAheadValidationWarning                                             <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> st/model_selection/_utils.py:675                                                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m──────────────────────────\u001b[0m\u001b[38;5;214m OneStepAheadValidationWarning \u001b[0m\u001b[38;5;214m───────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m One-step-ahead predictions are used for faster model comparison, but they may not    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m fully represent multi-step prediction performance. It is recommended to backtest the \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m final model for a more accurate multi-step performance estimate.                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : OneStepAheadValidationWarning                                             \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m st/model_selection/_utils.py:675                                                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------\n",
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 90.56433486938477\n",
      "Execution time one step ahead: 24.597376823425293\n",
      "Same lags   : False\n",
      "Same params : False\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48\n",
      " 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72]\n",
      "    params : {'n_estimators': 1200, 'max_depth': 8, 'learning_rate': 0.020288327487155415, 'gamma': 0.9893221948178936, 'reg_alpha': 0.0026751307734329544, 'reg_lambda': 0.0033431281459104997}\n",
      "    mean_absolute_error: 196.74829952595292\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [  1   2   3  23  24  25 167 168 169]\n",
      "    params : {'n_estimators': 1200, 'max_depth': 10, 'learning_rate': 0.056896300053531614, 'gamma': 0.2725691628660212, 'reg_alpha': 0.24605588251006993, 'reg_lambda': 0.9687485406819449}\n",
      "    mean_absolute_error: 191.37491441780287\n"
     ]
    }
   ],
   "source": [
    "# Dataset vic_electricity - ForecasterRecursive\n",
    "# ==============================================================================\n",
    "end_train = '2013-06-30 23:59:00'\n",
    "end_validation = '2013-11-30 23:59:00'\n",
    "exog_features = ['Temperature', 'Holiday']\n",
    "\n",
    "forecaster = ForecasterRecursive(\n",
    "                 estimator = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                 lags      = 10\n",
    "             )\n",
    "\n",
    "lags_grid = [48, 72, (1, 2, 3, 23, 24, 25, 167, 168, 169)]\n",
    "\n",
    "\n",
    "def search_space(trial):\n",
    "    search_space  = {\n",
    "        'n_estimators' : trial.suggest_int('n_estimators', 400, 1200, step=100),\n",
    "        'max_depth'    : trial.suggest_int('max_depth', 3, 10, step=1),\n",
    "        'learning_rate': trial.suggest_float('learning_rate', 0.01, 1),\n",
    "        'gamma'        : trial.suggest_float('gamma', 0, 1),\n",
    "        'reg_alpha'    : trial.suggest_float('reg_alpha', 0, 1),\n",
    "        'reg_lambda'   : trial.suggest_float('reg_lambda', 0, 1),\n",
    "        'lags'         : trial.suggest_categorical('lags', lags_grid)\n",
    "    } \n",
    "    return search_space\n",
    "\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark(\n",
    "    data                    = data_electricity,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'bayesian_search',\n",
    "    search_space            = search_space,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    target                  = 'Demand',\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 24,\n",
    "    metric                  = metric\n",
    ")\n",
    "\n",
    "results_bayesian_search.append([\n",
    "    'electricity',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭─────────────────────────── OneStepAheadValidationWarning ────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> One-step-ahead predictions are used for faster model comparison, but they may not    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> fully represent multi-step prediction performance. It is recommended to backtest the <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> final model for a more accurate multi-step performance estimate.                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : OneStepAheadValidationWarning                                             <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> st/model_selection/_utils.py:675                                                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m──────────────────────────\u001b[0m\u001b[38;5;214m OneStepAheadValidationWarning \u001b[0m\u001b[38;5;214m───────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m One-step-ahead predictions are used for faster model comparison, but they may not    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m fully represent multi-step prediction performance. It is recommended to backtest the \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m final model for a more accurate multi-step performance estimate.                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : OneStepAheadValidationWarning                                             \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m st/model_selection/_utils.py:675                                                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------\n",
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 16.454455375671387\n",
      "Execution time one step ahead: 0.6429948806762695\n",
      "Same lags   : True\n",
      "Same params : False\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48\n",
      " 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72]\n",
      "    params : {'alpha': 16.432489069228232}\n",
      "    mean_absolute_error: 307.13365278620506\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48\n",
      " 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72]\n",
      "    params : {'alpha': 0.36149961722510493}\n",
      "    mean_absolute_error: 300.87028133154746\n"
     ]
    }
   ],
   "source": [
    "# Dataset vic_electricity - ForecasterDirect\n",
    "# ==============================================================================\n",
    "forecaster = ForecasterDirect(\n",
    "                 estimator     = Ridge(random_state=123),\n",
    "                 transformer_y = StandardScaler(),\n",
    "                 lags          = 10,\n",
    "                 steps         = 24\n",
    "             )\n",
    "\n",
    "lags_grid = (48, 72, (1, 2, 3, 23, 24, 25, 167, 168, 169))\n",
    "\n",
    "\n",
    "def search_space(trial):\n",
    "    search_space  = {\n",
    "        'alpha': trial.suggest_float('alpha', 0.001, 1000, log=True),\n",
    "        'lags' : trial.suggest_categorical('lags', lags_grid)\n",
    "    }\n",
    "\n",
    "    return search_space\n",
    "\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark(\n",
    "    data                    = data_electricity,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'bayesian_search',\n",
    "    search_space            = search_space,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    target                  = 'Demand',\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 24,\n",
    "    metric                  = metric\n",
    ")\n",
    "\n",
    "results_bayesian_search.append([\n",
    "    'electricity',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭─────────────────────────── OneStepAheadValidationWarning ────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> One-step-ahead predictions are used for faster model comparison, but they may not    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> fully represent multi-step prediction performance. It is recommended to backtest the <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> final model for a more accurate multi-step performance estimate.                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : OneStepAheadValidationWarning                                             <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> st/model_selection/_utils.py:675                                                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m──────────────────────────\u001b[0m\u001b[38;5;214m OneStepAheadValidationWarning \u001b[0m\u001b[38;5;214m───────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m One-step-ahead predictions are used for faster model comparison, but they may not    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m fully represent multi-step prediction performance. It is recommended to backtest the \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m final model for a more accurate multi-step performance estimate.                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : OneStepAheadValidationWarning                                             \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m st/model_selection/_utils.py:675                                                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 3.746009349822998\n",
      "Execution time one step ahead: 2.683635950088501\n",
      "Same lags   : True\n",
      "Same params : False\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48]\n",
      "    params : {'n_estimators': 199, 'max_depth': 3, 'learning_rate': 0.01901626315047264}\n",
      "    135.45451272241843\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48]\n",
      "    params : {'n_estimators': 198, 'max_depth': 3, 'learning_rate': 0.06045266837878549}\n",
      "    123.59899056676193\n"
     ]
    }
   ],
   "source": [
    "# Dataset sales - ForecasterRecursiveMultiSeries\n",
    "# ==============================================================================\n",
    "end_train = '2014-05-15 23:59:00'\n",
    "end_validation = '2014-07-15 23:59:00'\n",
    "levels = ['item_1', 'item_2', 'item_3']\n",
    "exog_features = ['day_of_week']\n",
    "\n",
    "forecaster = ForecasterRecursiveMultiSeries(\n",
    "                 estimator          = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                 lags               = 24,\n",
    "                 encoding           = \"ordinal\",\n",
    "                 transformer_series = None,\n",
    "                 transformer_exog   = None,\n",
    "                 weight_func        = None,\n",
    "                 series_weights     = None,\n",
    "                 differentiation    = None,\n",
    "                 dropna_from_series = False,\n",
    "                 fit_kwargs         = None,\n",
    "                 forecaster_id      = None\n",
    "             )\n",
    "\n",
    "lags_grid = [48, 72]\n",
    "\n",
    "\n",
    "def search_space(trial):\n",
    "    search_space  = {\n",
    "        'n_estimators' : trial.suggest_int('n_estimators', 50, 200),\n",
    "        'max_depth'    : trial.suggest_int('max_depth', 3, 10, step=1),\n",
    "        'learning_rate': trial.suggest_float('learning_rate', 0.01, 1),\n",
    "        'lags'         : trial.suggest_categorical('lags', lags_grid)\n",
    "    } \n",
    "    return search_space\n",
    "\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark_multiseries(\n",
    "    data                    = data_sales,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'bayesian_search',\n",
    "    search_space            = search_space,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    levels                  = levels,\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 36,\n",
    "    metric                  = metric\n",
    ")\n",
    "\n",
    "results_bayesian_search.append([\n",
    "    'sales',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭─────────────────────────────── IgnoredArgumentWarning ───────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> `levels` argument have no use when the forecaster is of type                         <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> `ForecasterDirectMultiVariate`. The level of this forecaster is 'item_1', to predict <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> another level, change the `level` argument when initializing the forecaster.         <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : IgnoredArgumentWarning                                                    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> st/model_selection/_utils.py:891                                                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=IgnoredArgumentWarning)          <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m──────────────────────────────\u001b[0m\u001b[38;5;214m IgnoredArgumentWarning \u001b[0m\u001b[38;5;214m──────────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m `levels` argument have no use when the forecaster is of type                         \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m `ForecasterDirectMultiVariate`. The level of this forecaster is 'item_1', to predict \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m another level, change the `level` argument when initializing the forecaster.         \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : IgnoredArgumentWarning                                                    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m st/model_selection/_utils.py:891                                                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=IgnoredArgumentWarning)          \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭─────────────────────────────── IgnoredArgumentWarning ───────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> `levels` argument have no use when the forecaster is of type                         <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> `ForecasterDirectMultiVariate`. The level of this forecaster is 'item_1', to predict <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> another level, change the `level` argument when initializing the forecaster.         <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : IgnoredArgumentWarning                                                    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> st/model_selection/_utils.py:891                                                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=IgnoredArgumentWarning)          <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m──────────────────────────────\u001b[0m\u001b[38;5;214m IgnoredArgumentWarning \u001b[0m\u001b[38;5;214m──────────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m `levels` argument have no use when the forecaster is of type                         \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m `ForecasterDirectMultiVariate`. The level of this forecaster is 'item_1', to predict \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m another level, change the `level` argument when initializing the forecaster.         \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : IgnoredArgumentWarning                                                    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m st/model_selection/_utils.py:891                                                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=IgnoredArgumentWarning)          \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭─────────────────────────── OneStepAheadValidationWarning ────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> One-step-ahead predictions are used for faster model comparison, but they may not    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> fully represent multi-step prediction performance. It is recommended to backtest the <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> final model for a more accurate multi-step performance estimate.                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : OneStepAheadValidationWarning                                             <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> st/model_selection/_utils.py:675                                                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m──────────────────────────\u001b[0m\u001b[38;5;214m OneStepAheadValidationWarning \u001b[0m\u001b[38;5;214m───────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m One-step-ahead predictions are used for faster model comparison, but they may not    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m fully represent multi-step prediction performance. It is recommended to backtest the \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m final model for a more accurate multi-step performance estimate.                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : OneStepAheadValidationWarning                                             \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m st/model_selection/_utils.py:675                                                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=OneStepAheadValidationWarning)   \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭─────────────────────────────── IgnoredArgumentWarning ───────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> `levels` argument have no use when the forecaster is of type                         <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> `ForecasterDirectMultiVariate`. The level of this forecaster is 'item_1', to predict <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> another level, change the `level` argument when initializing the forecaster.         <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : IgnoredArgumentWarning                                                    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> st/model_selection/_utils.py:891                                                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=IgnoredArgumentWarning)          <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m──────────────────────────────\u001b[0m\u001b[38;5;214m IgnoredArgumentWarning \u001b[0m\u001b[38;5;214m──────────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m `levels` argument have no use when the forecaster is of type                         \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m `ForecasterDirectMultiVariate`. The level of this forecaster is 'item_1', to predict \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m another level, change the `level` argument when initializing the forecaster.         \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : IgnoredArgumentWarning                                                    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m st/model_selection/_utils.py:891                                                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=IgnoredArgumentWarning)          \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╭─────────────────────────────── IgnoredArgumentWarning ───────────────────────────────╮</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> `levels` argument have no use when the forecaster is of type                         <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> `ForecasterDirectMultiVariate`. The level of this forecaster is 'item_1', to predict <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> another level, change the `level` argument when initializing the forecaster.         <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>                                                                                      <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Category : IgnoredArgumentWarning                                                    <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Location :                                                                           <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> st/model_selection/_utils.py:891                                                     <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span> Suppress : warnings.simplefilter('ignore', category=IgnoredArgumentWarning)          <span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">│</span>\n",
       "<span style=\"color: #ffaf00; text-decoration-color: #ffaf00\">╰──────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[38;5;214m╭─\u001b[0m\u001b[38;5;214m──────────────────────────────\u001b[0m\u001b[38;5;214m IgnoredArgumentWarning \u001b[0m\u001b[38;5;214m──────────────────────────────\u001b[0m\u001b[38;5;214m─╮\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m `levels` argument have no use when the forecaster is of type                         \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m `ForecasterDirectMultiVariate`. The level of this forecaster is 'item_1', to predict \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m another level, change the `level` argument when initializing the forecaster.         \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m                                                                                      \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Category : IgnoredArgumentWarning                                                    \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Location :                                                                           \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m /home/ubuntu/anaconda3/envs/skforecast_15_py12/lib/python3.12/site-packages/skforeca \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m st/model_selection/_utils.py:891                                                     \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m│\u001b[0m Suppress : warnings.simplefilter('ignore', category=IgnoredArgumentWarning)          \u001b[38;5;214m│\u001b[0m\n",
       "\u001b[38;5;214m╰──────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 18.90007495880127\n",
      "Execution time one step ahead: 4.8505072593688965\n",
      "Same lags   : False\n",
      "Same params : False\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48]\n",
      "    params : {'n_estimators': 178, 'max_depth': 4, 'learning_rate': 0.029392307095288957}\n",
      "    98.66981600939468\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24\n",
      " 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48\n",
      " 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72]\n",
      "    params : {'n_estimators': 98, 'max_depth': 5, 'learning_rate': 0.23598059857016607}\n",
      "    101.07276932380157\n"
     ]
    }
   ],
   "source": [
    "# Dataset sales - ForecasterDirectMultiVariate\n",
    "# ==============================================================================\n",
    "forecaster = ForecasterDirectMultiVariate(\n",
    "                 estimator          = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                 lags               = 24,\n",
    "                 steps              = 5,\n",
    "                 level              = 'item_1',\n",
    "                 transformer_series = None,\n",
    "                 transformer_exog   = None,\n",
    "                 weight_func        = None,\n",
    "                 fit_kwargs         = None,\n",
    "                 forecaster_id      = None\n",
    "             )\n",
    "\n",
    "lags_grid = [48, 72]\n",
    "\n",
    "\n",
    "def search_space(trial):\n",
    "    search_space  = {\n",
    "        'n_estimators' : trial.suggest_int('n_estimators', 50, 200),\n",
    "        'max_depth'    : trial.suggest_int('max_depth', 3, 10, step=1),\n",
    "        'learning_rate': trial.suggest_float('learning_rate', 0.01, 1),\n",
    "        'lags'         : trial.suggest_categorical('lags', lags_grid)\n",
    "    }\n",
    "\n",
    "    return search_space\n",
    "\n",
    "\n",
    "time_1, time_2, metric_1, metric_2 = run_benchmark_multiseries(\n",
    "    data                    = data_sales,\n",
    "    forecaster_to_benchmark = forecaster,\n",
    "    search_method           = 'bayesian_search',\n",
    "    search_space            = search_space,\n",
    "    end_train               = end_train,\n",
    "    end_validation          = end_validation,\n",
    "    levels                  = levels,\n",
    "    exog_features           = exog_features,\n",
    "    steps                   = 5,\n",
    "    metric                  = metric\n",
    ")\n",
    "\n",
    "results_bayesian_search.append([\n",
    "    'sales',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1,\n",
    "    metric_2,\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Benchmark results\n",
      "-----------------\n",
      "Execution time backtesting   : 2.2047343254089355\n",
      "Execution time one step ahead: 0.6358184814453125\n",
      "Same lags   : True\n",
      "Same params : True\n",
      "\n",
      "Method: backtesting\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14]\n",
      "    params : {'n_estimators': 77, 'max_depth': 3}\n",
      "    208.60243551060555\n",
      "\n",
      "Method: one step ahead\n",
      "    lags   : [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14]\n",
      "    params : {'n_estimators': 77, 'max_depth': 3}\n",
      "    208.60243551060555\n"
     ]
    }
   ],
   "source": [
    "# Dataset series_dict - ForecasterRecursiveMultiSeries\n",
    "# ==============================================================================\n",
    "end_train = '2016-05-31 23:59:00'\n",
    "end_validation = '2016-07-31 23:59:00'\n",
    "levels = ['id_1000', 'id_1001', 'id_1002', 'id_1003', 'id_1004']\n",
    "series_dict_train = {k: v.loc[: end_train,] for k, v in series_dict.items()}\n",
    "exog_dict_train   = {k: v.loc[: end_train,] for k, v in exog_dict.items()}\n",
    "series_dict_test  = {k: v.loc[end_train:,] for k, v in series_dict.items()}\n",
    "exog_dict_test    = {k: v.loc[end_train:,] for k, v in exog_dict.items()}\n",
    "\n",
    "forecaster_to_benchmark = ForecasterRecursiveMultiSeries(\n",
    "                 estimator          = LGBMRegressor(random_state=123, verbose=-1),\n",
    "                 lags               = 24,\n",
    "                 encoding           = \"ordinal\",\n",
    "                 transformer_series = None,\n",
    "                 transformer_exog   = None,\n",
    "                 weight_func        = None,\n",
    "                 series_weights     = None,\n",
    "                 differentiation    = None,\n",
    "                 dropna_from_series = False,\n",
    "                 fit_kwargs         = None,\n",
    "                 forecaster_id      = None\n",
    "             )\n",
    "\n",
    "\n",
    "def search_space(trial):\n",
    "    search_space  = {\n",
    "        'n_estimators': trial.suggest_int('n_estimators', 50, 200),\n",
    "        'max_depth'   : trial.suggest_int('max_depth', 3, 7, step=1),\n",
    "        'lags'        : trial.suggest_categorical('lags', [7, 14])\n",
    "    } \n",
    "    return search_space\n",
    "\n",
    "\n",
    "# Backtesting\n",
    "forecaster = copy(forecaster_to_benchmark)\n",
    "cv = TimeSeriesFold(\n",
    "        initial_train_size = 100,\n",
    "        steps              = 24,\n",
    "        refit              = False,\n",
    "     )\n",
    "start  = time()\n",
    "results_1, _ = bayesian_search_forecaster_multiseries(\n",
    "                   forecaster         = forecaster,\n",
    "                   series             = {k: v.loc[: end_validation,] for k, v in series_dict.items()},\n",
    "                   exog               = {k: v.loc[: end_validation,] for k, v in exog_dict.items()},\n",
    "                   cv                 = cv,\n",
    "                   search_space       = search_space,\n",
    "                   n_trials           = 10,\n",
    "                   metric             = metric,\n",
    "                   return_best        = False,\n",
    "                   n_jobs             = 'auto',\n",
    "                   verbose            = False,\n",
    "                   show_progress      = False,\n",
    "                   suppress_warnings  = True\n",
    "               )\n",
    "end = time()\n",
    "time_1 = end - start\n",
    "best_params = results_1.loc[0, 'params']\n",
    "best_lags = results_1.loc[0, 'lags']\n",
    "forecaster.set_params(best_params)\n",
    "forecaster.set_lags(lags=best_lags)\n",
    "\n",
    "cv = TimeSeriesFold(\n",
    "        initial_train_size = 213,\n",
    "        steps              = 24,\n",
    "        refit              = False,\n",
    "     )\n",
    "metric_1, pred_1 = backtesting_forecaster_multiseries(\n",
    "                       forecaster         = forecaster,\n",
    "                       series             = series_dict,\n",
    "                       exog               = exog_dict,\n",
    "                       cv                 = cv,\n",
    "                       levels             = levels,\n",
    "                       metric             = metric,\n",
    "                       verbose            = False,\n",
    "                       show_progress      = False,\n",
    "                       suppress_warnings  = True\n",
    "                   )\n",
    "\n",
    "# One step ahead\n",
    "forecaster = copy(forecaster_to_benchmark)\n",
    "cv = OneStepAheadFold(initial_train_size = 100)\n",
    "start  = time()\n",
    "results_2, _ = bayesian_search_forecaster_multiseries(\n",
    "                   forecaster         = forecaster,\n",
    "                   series             = {k: v.loc[: end_validation,] for k, v in series_dict.items()},\n",
    "                   exog               = {k: v.loc[: end_validation,] for k, v in exog_dict.items()},\n",
    "                   cv                 = cv,\n",
    "                   levels             = levels,\n",
    "                   search_space       = search_space,\n",
    "                   n_trials           = 10,\n",
    "                   metric             = metric,\n",
    "                   return_best        = False,\n",
    "                   verbose            = False,\n",
    "                   show_progress      = False,\n",
    "                   suppress_warnings  = True\n",
    "               )\n",
    "end = time()\n",
    "time_2 = end - start\n",
    "best_params = results_2.loc[0, 'params']\n",
    "best_lags = results_2.loc[0, 'lags']\n",
    "forecaster.set_params(best_params)\n",
    "forecaster.set_lags(lags=best_lags)\n",
    "\n",
    "cv = TimeSeriesFold(\n",
    "        initial_train_size = 213,\n",
    "        steps              = 24,\n",
    "        refit              = False,\n",
    "     )\n",
    "metric_2, pred_2 = backtesting_forecaster_multiseries(\n",
    "                       forecaster         = forecaster,\n",
    "                       series             = series_dict,\n",
    "                       exog               = exog_dict,\n",
    "                       cv                 = cv,\n",
    "                       levels             = levels,\n",
    "                       metric             = metric,\n",
    "                       verbose            = False,\n",
    "                       show_progress      = False,\n",
    "                       suppress_warnings  = True\n",
    "                   )\n",
    "\n",
    "print(\"Benchmark results\")\n",
    "print(\"-----------------\")\n",
    "print('Execution time backtesting   :', time_1)\n",
    "print('Execution time one step ahead:', time_2)\n",
    "print(f\"Same lags   : {np.array_equal(results_1.loc[0, 'lags'], results_2.loc[0, 'lags'])}\")\n",
    "print(f\"Same params : {results_1.loc[0, 'params'] == results_2.loc[0, 'params']}\")\n",
    "print(\"\")\n",
    "print(\"Method: backtesting\")\n",
    "print(f\"    lags   : {results_1.loc[0, 'lags']}\")\n",
    "print(f\"    params : {results_1.loc[0, 'params']}\")\n",
    "print(f\"    {metric_1.loc[0, metric]}\")\n",
    "print(\"\")\n",
    "print(\"Method: one step ahead\")\n",
    "print(f\"    lags   : {results_2.loc[0, 'lags']}\")\n",
    "print(f\"    params : {results_2.loc[0, 'params']}\")\n",
    "print(f\"    {metric_2.loc[0, metric]}\")\n",
    "\n",
    "results_bayesian_search.append([\n",
    "    'series_dict',\n",
    "    type(forecaster).__name__,\n",
    "    time_1,\n",
    "    time_2,\n",
    "    metric_1.loc[0, metric],\n",
    "    metric_2.loc[0, metric],\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "index",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "dataset",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "forecaster",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "time_search_backtesting",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "time_search_one_step",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "metric_backtesting",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "metric_one_step",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "ratio_speed",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "ratio_metric",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "dataset_forecaster",
         "rawType": "object",
         "type": "string"
        }
       ],
       "conversionMethod": "pd.DataFrame",
       "ref": "5a4655fb-67b3-4af4-bf68-6fe782db50b6",
       "rows": [
        [
         "0",
         "bike_sharing",
         "ForecasterRecursive",
         "87.15898752212524",
         "27.95840358734131",
         "55.80577702511616",
         "55.80577702511616",
         "3.12",
         "1.0",
         "bike_sharing \n Recursive"
        ],
        [
         "1",
         "bike_sharing",
         "ForecasterDirect",
         "17.606075286865234",
         "0.9842092990875244",
         "79.1498337214025",
         "111.96208734026862",
         "17.89",
         "0.71",
         "bike_sharing \n Direct"
        ],
        [
         "2",
         "website",
         "ForecasterRecursive",
         "1.0920460224151611",
         "0.26500821113586426",
         "136.76802274106467",
         "173.5282998809151",
         "4.12",
         "0.79",
         "website \n Recursive"
        ],
        [
         "3",
         "website",
         "ForecasterDirect",
         "1.5587255954742432",
         "0.3095226287841797",
         "139.40123604696382",
         "153.6723680506666",
         "5.04",
         "0.91",
         "website \n Direct"
        ],
        [
         "4",
         "electricity",
         "ForecasterRecursive",
         "90.56433486938477",
         "24.597376823425293",
         "196.74829952595292",
         "191.37491441780287",
         "3.68",
         "1.03",
         "electricity \n Recursive"
        ],
        [
         "5",
         "electricity",
         "ForecasterDirect",
         "16.454455375671387",
         "0.6429948806762695",
         "307.13365278620506",
         "300.87028133154746",
         "25.59",
         "1.02",
         "electricity \n Direct"
        ],
        [
         "6",
         "sales",
         "ForecasterRecursiveMultiSeries",
         "3.746009349822998",
         "2.683635950088501",
         "135.45451272241843",
         "123.59899056676193",
         "1.4",
         "1.1",
         "sales \n RecursiveMultiSeries"
        ],
        [
         "7",
         "sales",
         "ForecasterDirectMultiVariate",
         "18.90007495880127",
         "4.8505072593688965",
         "98.66981600939468",
         "101.07276932380157",
         "3.9",
         "0.98",
         "sales \n DirectMultiVariate"
        ],
        [
         "8",
         "series_dict",
         "ForecasterRecursiveMultiSeries",
         "2.2047343254089355",
         "0.6358184814453125",
         "208.60243551060555",
         "208.60243551060555",
         "3.47",
         "1.0",
         "series_dict \n RecursiveMultiSeries"
        ]
       ],
       "shape": {
        "columns": 9,
        "rows": 9
       }
      },
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>dataset</th>\n",
       "      <th>forecaster</th>\n",
       "      <th>time_search_backtesting</th>\n",
       "      <th>time_search_one_step</th>\n",
       "      <th>metric_backtesting</th>\n",
       "      <th>metric_one_step</th>\n",
       "      <th>ratio_speed</th>\n",
       "      <th>ratio_metric</th>\n",
       "      <th>dataset_forecaster</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>bike_sharing</td>\n",
       "      <td>ForecasterRecursive</td>\n",
       "      <td>87.158988</td>\n",
       "      <td>27.958404</td>\n",
       "      <td>55.805777</td>\n",
       "      <td>55.805777</td>\n",
       "      <td>3.12</td>\n",
       "      <td>1.00</td>\n",
       "      <td>bike_sharing \\n Recursive</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>bike_sharing</td>\n",
       "      <td>ForecasterDirect</td>\n",
       "      <td>17.606075</td>\n",
       "      <td>0.984209</td>\n",
       "      <td>79.149834</td>\n",
       "      <td>111.962087</td>\n",
       "      <td>17.89</td>\n",
       "      <td>0.71</td>\n",
       "      <td>bike_sharing \\n Direct</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>website</td>\n",
       "      <td>ForecasterRecursive</td>\n",
       "      <td>1.092046</td>\n",
       "      <td>0.265008</td>\n",
       "      <td>136.768023</td>\n",
       "      <td>173.528300</td>\n",
       "      <td>4.12</td>\n",
       "      <td>0.79</td>\n",
       "      <td>website \\n Recursive</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>website</td>\n",
       "      <td>ForecasterDirect</td>\n",
       "      <td>1.558726</td>\n",
       "      <td>0.309523</td>\n",
       "      <td>139.401236</td>\n",
       "      <td>153.672368</td>\n",
       "      <td>5.04</td>\n",
       "      <td>0.91</td>\n",
       "      <td>website \\n Direct</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>electricity</td>\n",
       "      <td>ForecasterRecursive</td>\n",
       "      <td>90.564335</td>\n",
       "      <td>24.597377</td>\n",
       "      <td>196.748300</td>\n",
       "      <td>191.374914</td>\n",
       "      <td>3.68</td>\n",
       "      <td>1.03</td>\n",
       "      <td>electricity \\n Recursive</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>electricity</td>\n",
       "      <td>ForecasterDirect</td>\n",
       "      <td>16.454455</td>\n",
       "      <td>0.642995</td>\n",
       "      <td>307.133653</td>\n",
       "      <td>300.870281</td>\n",
       "      <td>25.59</td>\n",
       "      <td>1.02</td>\n",
       "      <td>electricity \\n Direct</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>sales</td>\n",
       "      <td>ForecasterRecursiveMultiSeries</td>\n",
       "      <td>3.746009</td>\n",
       "      <td>2.683636</td>\n",
       "      <td>135.454513</td>\n",
       "      <td>123.598991</td>\n",
       "      <td>1.40</td>\n",
       "      <td>1.10</td>\n",
       "      <td>sales \\n RecursiveMultiSeries</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>sales</td>\n",
       "      <td>ForecasterDirectMultiVariate</td>\n",
       "      <td>18.900075</td>\n",
       "      <td>4.850507</td>\n",
       "      <td>98.669816</td>\n",
       "      <td>101.072769</td>\n",
       "      <td>3.90</td>\n",
       "      <td>0.98</td>\n",
       "      <td>sales \\n DirectMultiVariate</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>series_dict</td>\n",
       "      <td>ForecasterRecursiveMultiSeries</td>\n",
       "      <td>2.204734</td>\n",
       "      <td>0.635818</td>\n",
       "      <td>208.602436</td>\n",
       "      <td>208.602436</td>\n",
       "      <td>3.47</td>\n",
       "      <td>1.00</td>\n",
       "      <td>series_dict \\n RecursiveMultiSeries</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        dataset                      forecaster  time_search_backtesting  \\\n",
       "0  bike_sharing             ForecasterRecursive                87.158988   \n",
       "1  bike_sharing                ForecasterDirect                17.606075   \n",
       "2       website             ForecasterRecursive                 1.092046   \n",
       "3       website                ForecasterDirect                 1.558726   \n",
       "4   electricity             ForecasterRecursive                90.564335   \n",
       "5   electricity                ForecasterDirect                16.454455   \n",
       "6         sales  ForecasterRecursiveMultiSeries                 3.746009   \n",
       "7         sales    ForecasterDirectMultiVariate                18.900075   \n",
       "8   series_dict  ForecasterRecursiveMultiSeries                 2.204734   \n",
       "\n",
       "   time_search_one_step  metric_backtesting  metric_one_step  ratio_speed  \\\n",
       "0             27.958404           55.805777        55.805777         3.12   \n",
       "1              0.984209           79.149834       111.962087        17.89   \n",
       "2              0.265008          136.768023       173.528300         4.12   \n",
       "3              0.309523          139.401236       153.672368         5.04   \n",
       "4             24.597377          196.748300       191.374914         3.68   \n",
       "5              0.642995          307.133653       300.870281        25.59   \n",
       "6              2.683636          135.454513       123.598991         1.40   \n",
       "7              4.850507           98.669816       101.072769         3.90   \n",
       "8              0.635818          208.602436       208.602436         3.47   \n",
       "\n",
       "   ratio_metric                   dataset_forecaster  \n",
       "0          1.00            bike_sharing \\n Recursive  \n",
       "1          0.71               bike_sharing \\n Direct  \n",
       "2          0.79                 website \\n Recursive  \n",
       "3          0.91                    website \\n Direct  \n",
       "4          1.03             electricity \\n Recursive  \n",
       "5          1.02                electricity \\n Direct  \n",
       "6          1.10        sales \\n RecursiveMultiSeries  \n",
       "7          0.98          sales \\n DirectMultiVariate  \n",
       "8          1.00  series_dict \\n RecursiveMultiSeries  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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S4tMKFWsgGybmpXLQE9PBJfXH4UFTkREREREKUrXOxb/YmpiLDcvRS77rChRJB9CfoTD51sAth84i9GDusDDyxdePn6YNKIn/AKCZJ2yP3l448adp1gx6z9MXrgRBvr6WDBlCM5cdoZfQJC6TouIiIiIKMPTqMKiTImCOLH99yhScycMBAAcOXsdY2etwcbdJ2BqYoxlM0fCwtwMj13eosfw2YiJjZPtM3LaCiycOhRHtyxAQoIUjtfvYcbSrel+LkREREREukSjCov7T14jR9lWf91mucMBLHc4kOL6kNBwjJi6QtWhERERERHRX2jm5A1ERERERKRV0r2wkEql6X1IIiIiIiJKY1ozKhQREREREWmudO1j8T0oBDnLt0nPQxIRERERUToQXFgUzJcTXds0RG77bMhskQn/f0NCKgW6DJkh9DBERERERKTBBBUWHVrUw+q5oxEXHw/3zz4ICQ1Psg2ffKJUmbpXZU3FAoBTD5W1R0REREQpE1RYjB/aDa8/uKPniDkICglVVUxERERERKRlBHXezmprjcOnr7KoICIiIiLScYIKi3eunshqa62qWIiIiIiISEsJKizmrtyBbm0boWKZoqqKh4iIiIiItJCgPhYj+nZAWHgkTu1cgo/uX+DzLQAJkgS5baRSKfqNXSgoSCIiIiIi0myCCotihfNCKgV8vn2HmakJCufPnWQbzrRNRERERJTxCSosqjQfqKo4iIiIiIhIiwnqY0FERERERASoYObtX8xMTWCRyRR6eklrFZ9vAao6DBERERERaSDBhUXvTs0wuFdb5LHPmuI2uSq0FXoYIiIiIiLSYIIeherVsSkWTR0KT6+vWLpxP0QiEbYdOIsNu07APzAEbz96Yvzc9aqKlYiIiIiINJSgwqJ/t1ZwuueCniPn4MCJywCA685PsHTDPtRtPxxmZiawymyukkCJiIiIiEhzCXoUKk/ObNh95AIAIC4+HgBgYJDYZFh4JA6dvII+nZtjy77TwqLUNlP3qqypWACuTj1U1h4A6N8Xq7Q9IiIiIiJBdyzCwiOgL078kBoeEYWo6BjkyJZFtj48Mgp2WayERUhERERERBpPUGHx/pMXihfOK3v97OUH9OnUHNnsrJEjaxb07NAU7p99hMZIREREREQaTlBhcdLxJooUzAPDn48/rdh8EAXz5cTjizvx0HE7CuS1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",
      "text/plain": [
       "<Figure size 800x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Results\n",
    "# ==============================================================================\n",
    "summarize_results(\n",
    "    results   = results_bayesian_search,\n",
    "    metric    = metric,\n",
    "    plot      = True,\n",
    "    fig_size  = (8, 6),\n",
    "    title     = 'Bayesian search using backtesting vs one-step-ahead',\n",
    "    save_plot = \"../img/bayesian_search_benchmarck.png\"\n",
    ")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "skforecast_15_py12",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.9"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
